zoukankan      html  css  js  c++  java
  • 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 }
    人一我十,人十我万!追逐青春的梦想,怀着自信的心,永不放弃!仿佛已看到希望,尽管还在远方
  • 相关阅读:
    UVA 1386 Cellular Automaton
    ZOJ 3331 Process the Tasks
    CodeForces 650B Image Preview
    CodeForces 650A Watchmen
    CodeForces 651B Beautiful Paintings
    CodeForces 651A Joysticks
    HUST 1601 Shepherd
    HUST 1602 Substring
    HUST 1600 Lucky Numbers
    POJ 3991 Seinfeld
  • 原文地址:https://www.cnblogs.com/83131yyl/p/5058134.html
Copyright © 2011-2022 走看看