BZOJ 1003 物流运输 长歌当哭!

   真是很生气啊!这道题简直整整花了我一天的时间。自己怎么这么弱呢?

   算了,还是来聊一聊这道题的解题历程吧!一开始打算枚举从起点到终点的每条路径后再去动态规划。的确一开始的版本就是这样的。结果TLE了。之后打算再次版本上再去优化,曾想过把map改成数组,把深搜改成dijkstra,还打算把动态数组改成数组,由于一开始的动态规划是按照每一天推到下一天的,所以也曾把这个改成一个区间去推。但是最终在多次TLE后,我换回了WA。内心无比悲痛。无奈之下,跑去看了别人的题解,我去,这么简单。算了,真的得加把劲,多学一点。

   讲一讲最终的思路吧(在别人的题解的指导下)!是这样的因为这数据实在是太小了(n<=100,m<=20,不是很小吗?)所以我们可以对于i <= n, j <= n 分别进行dijkstra,求出这段时间内的最短路,并记录在一个数组cost里面。 最后设f[i]为到第i天为止时最少费用, 则状态转移方程可表示为 f[j] = min(f[j], f[i]+cost[i+1][j]+k]) (j < i ), 最终结果是f[n]-k。

要加油啊!

   启示:此题用一个sum数组来累加一个码头不能通行的天数,那么就能很快地去判断该码头在第几天是否能通行。

           对解题思路的一种转换。在数据较小时,可以进行多次的最短路算法,来实现预定目标。(而不一定要一次)。

这是此题的代码

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<queue>
 4 #include<cstring>
 5 #define clr(i,j) memset(i,j,sizeof(i));
 6 #define rep(i,j,k) for(int i = j; i <= k; i++)
 7 using namespace std;
 8 
 9 struct edge{
10 int to, key;
11 edge* next;
12 };
13 
14 edge edges[30000], *head[25], *pt; 
15 int dis[25] = {0}, done[25] = {0}, cost[105][105] = {0}, n, m;
16 int sum[25][105] = {0}, dp[105] = {0};
17 bool can[25][105] = {0};
18 
19 int read()
20 {
21     int s = 0, t = 1; char c = getchar();
22     while( !isdigit(c) ){
23         if( c == '-' ) t = -1; c = getchar();
24     } 
25     while( isdigit(c) ){
26         s = s * 10 + c - '0'; c = getchar();
27     }
28     return s * t;
29 }
30 
31 void SPFA()
32 {
33     int f[100] = {0}; 
34     rep(i,1,n){
35         rep(j,i,n){
36             memset(dis,127,sizeof(dis)); memset(done,0,sizeof(done));
37             int s = 0, t = 1; f[1] = 1, dis[1] = 0, done[1] = 1;
38             while( s < t ){
39                 int now = f[++s];
40                 for(edge*l = head[now]; l; l = l->next){
41                     int to = l->to, key = l->key;
42                     if( sum[to][j] - sum[to][i-1] != 0 ) continue;
43                     if( dis[to] > dis[now]+key ){
44                         dis[to] = dis[now] + key;
45                         if( !done[to] ) f[++t] = to, done[to] = 1;
46                     }
47                 }
48                 done[now] = 0;  
49             }
50             if( dis[m] > 10000000) {
51                 cost[i][j] = dis[m];
52             }
53             else cost[i][j] = (j-i+1)*dis[m];
54         }
55     }
56 }
57 
58 void add_edge(int x,int y,int key){
59    pt->to = x, pt->key = key, pt->next = head[y], head[y] = pt++;
60    pt->to = y, pt->key = key, pt->next = head[x], head[x] = pt++;
61 }
62 
63 int main()
64 {
65     n = read(), m = read();
66     int k = read(), e = read();
67     pt = edges;
68     rep(i,1,e){
69         int x = read(), y = read(), key = read();
70         add_edge(x,y,key);
71     }
72     int d = read(); 
73     rep(j,1,d){
74         int now = read(), x = read(), y = read();
75         rep(i,x,y){
76             can[now][i] = 1;
77         }
78     }
79     rep(i,1,m){
80         rep(j,1,n){
81             sum[i][j] = sum[i][j-1] + can[i][j]; 
82         }
83     }
84     SPFA();
85     clr(dp,60);
86     dp[0] = 0;
87     rep(i,1,n){
88         rep(j,0,i-1){
89             dp[i] = min(dp[i],dp[j]+cost[j+1][i]+k);
90         }
91     }
92     cout<<dp[n]-k<<endl;
93     return 0;
94 }

   这是我之前的代码,如果大神知道错在哪?请多多指教:(和上面的代码比起来弱多了,上面的代码跑完此题仅28ms)

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<vector>
  4 #include<cstring>
  5 #include<queue>
  6 #define rep(i,j,k) for(int i = j; i <= k; i++)
  7 #define clr(i,j) memset(i,j,sizeof(i))
  8 #define maxn 1005
  9 using namespace std;
 10    
 11 int tot = 0, dp[105] = {0}, cost[maxn*20] = {0}, path[maxn*20] = {0};
 12 int dist[maxn*3000] = {0};
 13 int n, m, xk, e;
 14 int p[maxn*3000];
 15 vector<int> day[105];
 16   
 17 struct node{
 18 int key, end;
 19 };
 20   
 21 vector<node> f[105];
 22   
 23 int read()
 24 {
 25     int s = 0, t = 1; char c = getchar();
 26     while( !isdigit(c) ){
 27         if( c == '-' ) t = -1; c = getchar();
 28     }
 29     while( isdigit(c) ){
 30         s = s * 10 + c - '0'; c = getchar();
 31     }
 32     return s * t;
 33 }
 34    
 35 struct edge{
 36 int to, key;
 37 edge* next;
 38 };
 39   
 40 struct nod{
 41 int r, u, now;
 42 bool operator < (const nod& rhs ) const{
 43    return r > rhs.r;
 44 }
 45 };
 46 priority_queue<nod> q;
 47   
 48    
 49 edge edges[maxn], *pt, *head[maxn];
 50    
 51 void add_edge(int x,int y,int val)
 52 {
 53     pt->to = y, pt->key = val, pt->next = head[x], head[x] = pt++;
 54     pt->to = x, pt->key = val, pt->next = head[y], head[y] = pt++;
 55 }
 56    
 57 void dijkstra()
 58 {
 59     clr(dist,127);
 60     dist[2] = 0;
 61     q.push((nod){0,2,1});
 62     while( !q.empty() ){
 63           nod x = q.top(); q.pop();
 64           int now = x.u;
 65           if( dist[now] != x.r )  continue;
 66           int k = x.now;
 67           if( k == m ){
 68              int zhi = p[now];
 69              if( zhi ){
 70                 if( cost[zhi] > x.r ){
 71                    cost[zhi] = x.r;
 72                 }
 73                 continue;
 74              }
 75             p[now] = ++tot;
 76             path[tot] = now; 
 77             cost[tot] = x.r;
 78             continue;
 79          }
 80          for(edge*i = head[k]; i ; i = i->next)
 81          {
 82              int y = i->to;
 83              if( now & (1<<y) ) continue;
 84              int to = now|(1<<y), key = i->key;
 85              if( dist[to] > dist[now] + key ){
 86                 dist[to] = dist[now] + key;
 87                 q.push((nod){dist[to],to,y});
 88              }
 89          }
 90           
 91     }  
 92 }
 93    
 94 int main()
 95 {
 96     n = read(), m = read(), xk = read(), e = read();
 97     pt = edges;
 98     rep(i,1,e){
 99         int x = read(), y = read(), key = read();
100         add_edge(x,y,key);
101     }
102     int k = read();
103     rep(i,1,k){
104         int  z = read(), x = read(), y = read();
105         rep(j,x,y){
106             day[j].push_back(z);
107         }
108     }
109     dijkstra();
110     int be = 0;
111     bool begin = 0;
112     rep(l,1,tot){
113         be = 0, begin = 0;
114         rep(i,1,n){
115          int s = day[i].size();
116          bool ok = 1;
117          rep(j,0,s-1){
118             if( (1<<day[i][j]) & path[l] ){
119                 if( !begin ) {
120                     ok = 0;
121                     break;
122                 }
123                 f[be-1].push_back((node){cost[l]*(i-be),i-1});
124                 ok = 0;
125                 begin = 0;
126                 break;
127             }
128          }
129          if( !begin && ok ){
130             be = i;
131             begin = 1;
132          }
133     }
134       if( begin ) f[be-1].push_back((node){cost[l]*(n+1-be),n});
135     }
136       
137     clr(dp,127);
138     int s = f[0].size();
139     rep(i,0,s-1){
140         node x = f[0][i];
141         int y = x.end, key = x.key;
142         dp[y] = min(dp[y],key);
143     }
144     rep(i,1,n){
145         int s = f[i].size();
146         rep(j,0,s-1){
147            node x = f[i][j];
148            int to = x.end, key = x.key;
149            dp[to] = min(dp[to],dp[i]+key+xk);   
150         }
151     }
152     cout<<dp[n]<<endl;
153     return 0;
154 }

 

posted on 2015-12-18 20:19  83131  阅读(118)  评论(0编辑  收藏  举报

导航