Hdu--4784(Spfa,优先队列,DP)

2014-11-07 23:34:39

思路:这题让我无语凝噎。首先想到用数组来存状态,因为N,B,K,T都比较小,所以可以直接存在dp[N][B][K][T]数组里,dp[v][b][k][t]表示当前在v点,身上有b袋盐,在第k平行宇宙,并且剩t分钟时间,用的是Spfa来松弛dp数组的值(说法可能不太准),这里用了一个优先队列来优化效率,t越大的越先考虑,为什么这样能优化呢?我们发现如果先考虑t大的,那么其会更新比t小的t’的dp;而如果先考虑t比较小的,去更新t更小的,这样当考虑较大的t时,较小的t又会被重新考虑(更新)一次,造成效率低下。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <cmath>
  5 #include <vector>
  6 #include <queue>
  7 #include <iostream>
  8 #include <algorithm>
  9 using namespace std;
 10 const int maxn = 201;
 11 
 12 inline int Read(){
 13        int x = 0;char ch = getchar();
 14        while(ch < '0' || ch > '9'){ch = getchar();}
 15        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
 16        return x;
 17 }
 18 
 19 struct node{
 20     int a,b,c,d;
 21     node(int ta,int tb,int tc,int td) : a(ta),b(tb),c(tc),d(td) {}
 22     bool operator < (const node &x) const{
 23         return d < x.d;
 24     }
 25 };
 26 
 27 int C,T,N,M,B,K,R,ans;
 28 int pri[6][101];
 29 int dp[101][6][6][201];
 30 int inq[101][6][6][201];
 31 int first[maxn],next[maxn],ver[maxn],tim[maxn],fee[maxn],ecnt;
 32 priority_queue<node> Q;
 33 
 34 void Init(){
 35     memset(inq,0,sizeof(inq));
 36     memset(first,-1,sizeof(first));
 37     memset(dp,0,sizeof(dp));
 38     while(!Q.empty()) Q.pop();
 39     ans = -1;
 40     ecnt = 0;
 41 }
 42 
 43 void Add_edge(int u,int v,int t,int f){
 44     next[++ecnt] = first[u];
 45     ver[ecnt] = v;
 46     tim[ecnt] = t;
 47     fee[ecnt] = f;
 48     first[u] = ecnt;
 49 }
 50 
 51 void Append(int a,int b,int c,int d){
 52     if(!inq[a][b][c][d]){
 53         Q.push(node(a,b,c,d));
 54         inq[a][b][c][d] = 1;
 55     }
 56 }
 57 
 58 void Bfs(){
 59     int v,tt,tf,nextk;
 60     dp[1][0][0][T] = R;
 61     Q.push(node(1,0,0,T));
 62     inq[1][0][0][T] = 1;
 63     while(!Q.empty()){
 64         node x = Q.top();
 65         Q.pop();
 66         inq[x.a][x.b][x.c][x.d] = 0;
 67         int tmp = dp[x.a][x.b][x.c][x.d];
 68         nextk = (x.c + 1) % K;
 69         for(int i = first[x.a]; i != -1; i = next[i]){
 70             v = ver[i];
 71             tt = tim[i];
 72             tf = fee[i];
 73             if(x.d >= tt && tmp >= tf){ //能去下一点
 74                 if(v == 1 && x.c != 0)
 75                     continue;
 76                 if(v == N){
 77                     if(x.c == 0)
 78                         ans = max(ans,tmp - tf);
 79                 }
 80                 else{
 81                     if(tmp - tf > dp[v][x.b][x.c][x.d - tt]){
 82                         //去下点,不行动
 83                         dp[v][x.b][x.c][x.d - tt] = tmp - tf;
 84                         Append(v,x.b,x.c,x.d - tt);
 85                     }
 86                     if(v != 1&& x.b < B  &&tmp - tf - pri[x.c][v] > dp[v][x.b + 1][x.c][x.d - tt]){
 87                         //去下点,买
 88                         dp[v][x.b + 1][x.c][x.d - tt] = tmp - tf - pri[x.c][v];
 89                         Append(v,x.b + 1,x.c,x.d - tt);
 90                     }
 91                     if(v != 1 && x.b > 0 && tmp - tf + pri[x.c][v] > dp[v][x.b - 1][x.c][x.d - tt]){
 92                         //去下点,卖
 93                         dp[v][x.b - 1][x.c][x.d - tt] = tmp - tf + pri[x.c][v];
 94                         Append(v,x.b - 1,x.c,x.d - tt);
 95                     }
 96                 }
 97             }
 98         }
 99         if(x.d > 0 && x.a != 1 ){
100             if(tmp >dp[x.a][x.b][nextk][x.d - 1]){
101                 //去下个宇宙,不行动
102                 dp[x.a][x.b][nextk][x.d - 1] = tmp;
103                 Append(x.a,x.b,nextk,x.d - 1);
104             }
105             if(x.b < B &&  tmp - pri[nextk][x.a] > dp[x.a][x.b + 1][nextk][x.d - 1]){
106                 //去下个宇宙,买
107                 dp[x.a][x.b + 1][nextk][x.d - 1] = tmp - pri[nextk][x.a];
108                 Append(x.a,x.b + 1,nextk,x.d - 1);
109             }
110             if(x.b > 0 &&  tmp + pri[nextk][x.a] > dp[x.a][x.b - 1][nextk][x.d - 1]){
111                 //去下个宇宙,卖
112                 dp[x.a][x.b - 1][nextk][x.d - 1] = tmp + pri[nextk][x.a];
113                 Append(x.a,x.b - 1,nextk,x.d - 1);
114             }
115         }
116     }
117 }
118 
119 int main(){
120     int a,b,c,d;
121     scanf("%d",&C);
122     for(int Case = 1; Case <= C; ++Case){
123         Init();
124         N = Read(); M = Read(); B = Read(); K = Read(); R = Read(); T = Read();
125         for(int i = 0; i < K; ++i)
126             for(int j = 1; j <= N; ++j)
127                 pri[i][j] = Read();
128         for(int i = 1; i <= M; ++i){
129             a = Read(); b = Read(); c = Read(); d = Read();
130             Add_edge(a,b,c,d);
131         }
132         Bfs();
133         printf("Case #%d: ",Case);
134         if(ans == -1) printf("Forever Alone\n");
135         else    printf("%d\n",ans);
136     }
137     return 0;
138 }

 

posted @ 2014-11-07 23:37  Naturain  阅读(193)  评论(0编辑  收藏  举报