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 }
    人一我十,人十我万!追逐青春的梦想,怀着自信的心,永不放弃!仿佛已看到希望,尽管还在远方
  • 相关阅读:
    char与unsigned char的区别
    C语言 —— sprintf()函数
    char *s 与 char s[ ]的区别
    打印不同对象的字节表示 ( 对int*强制转换成unsigned char*的理解 )
    洛谷P2242 公路维修问题(Road)
    洛谷P1209 [USACO1.3]修理牛棚 Barn Repair
    洛谷P1345 [USACO5.4]奶牛的电信Telecowmunication
    洛谷P2246 SAC#1
    Bzoj4300 绝世好题
    Uva1398 Meteor
  • 原文地址:https://www.cnblogs.com/83131yyl/p/5058134.html
Copyright © 2011-2022 走看看