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 }