分析:把时间作为优先队列的条件、然后bfs、
d[i][j][k][p]表示第i个城市、第j时刻、在第K维空间、有W包盐的最大价值
#include<stdio.h> #include<string.h> #include<queue> #include<algorithm> using namespace std; #define INF 0x7ffffff const int N=105; const int M=205; int n,m,b,k,r,t; //第i个城市、第j分钟、第K维空间、有P包盐的最大价值 int d[N][205][6][6]; bool vis[N][205][6][6]; int num[6][105]; int cnt; struct edges { int to,next,val,time; }edge[M]; struct node { int u,time,k,b; friend bool operator <(node a,node b) { return a.time>b.time; } }; int head[N]; void init() { cnt=0; memset(head,-1,sizeof(head)); } int bfs() { priority_queue<node>q; memset(vis,false,sizeof(vis)); memset(d,0xff,sizeof(d)); node now,tmp; now.b=0; now.u=1; now.k=0; now.time=0; d[1][0][0][0]=r; q.push(now); vis[1][0][0][0]=true; bool flag=false; while(!q.empty()) { now=q.top(); q.pop(); if(now.time>t)break; if(now.u==n)continue; //到下一个城市 for(int i=head[now.u];i!=-1;i=edge[i].next) { int w=edge[i].to; int f_cost=d[now.u][now.time][now.k][now.b]-edge[i].val; int f_time=now.time+edge[i].time; if(f_time>t||f_cost<0)continue; if(w==n&&now.k!=0)continue; if(w==n)flag=true; tmp.u=w; tmp.k=now.k; tmp.time=f_time; if(now.u!=1&&now.u!=n) { //买盐 如果在当前城市买了一袋盐且比以前的价值大 if(now.b+1<=b&&f_cost-num[now.k][now.u]>d[w][f_time][now.k][now.b+1]) { d[w][f_time][now.k][now.b+1]=f_cost-num[now.k][now.u]; tmp.b=now.b+1; if(!vis[tmp.u][tmp.time][tmp.k][tmp.b]) { q.push(tmp); vis[tmp.u][tmp.time][tmp.k][tmp.b]=true; } } //卖盐 if(now.b>0&&f_cost+num[now.k][now.u]>d[w][f_time][now.k][now.b-1]) { d[w][f_time][now.k][now.b-1]=f_cost+num[now.k][now.u]; tmp.b=now.b-1; if(!vis[tmp.u][tmp.time][tmp.k][tmp.b]) { q.push(tmp); vis[tmp.u][tmp.time][tmp.k][tmp.b]=true; } } } //不交易 if(f_cost>d[w][f_time][now.k][now.b]) { d[w][f_time][now.k][now.b]=f_cost; tmp.b=now.b; if(!vis[tmp.u][tmp.time][tmp.k][tmp.b]) { q.push(tmp); vis[tmp.u][tmp.time][tmp.k][tmp.b]=true; } } } //穿越 if(now.u!=1&&now.u!=n) { int f_cost=d[now.u][now.time][now.k][now.b]; tmp.u=now.u; tmp.k=(now.k+1)%k; tmp.time=now.time+1; if(tmp.time>t)continue; //买盐 if(now.b+1<=b&&f_cost-num[now.k][now.u]>d[now.u][tmp.time][tmp.k][now.b+1]) { d[now.u][tmp.time][tmp.k][now.b+1]=f_cost-num[now.k][now.u]; tmp.b=now.b+1; if(!vis[tmp.u][tmp.time][tmp.k][tmp.b]) { q.push(tmp); vis[tmp.u][tmp.time][tmp.k][tmp.b]=true; } } //卖盐 if(now.b>0&&f_cost+num[now.k][now.u]>d[now.u][tmp.time][tmp.k][now.b-1]) { d[now.u][tmp.time][tmp.k][now.b-1]=f_cost+num[now.k][now.u]; tmp.b=now.b-1; if(!vis[tmp.u][tmp.time][tmp.k][tmp.b]) { q.push(tmp); vis[tmp.u][tmp.time][tmp.k][tmp.b]=true; } } tmp.b=now.b; //不交易 if(f_cost>d[now.u][tmp.time][tmp.k][tmp.b]) { d[now.u][tmp.time][tmp.k][tmp.b]=f_cost; if(!vis[tmp.u][tmp.time][tmp.k][tmp.b]) { q.push(tmp); vis[tmp.u][tmp.time][tmp.k][tmp.b]=true; } } } } if(!flag)return -1; int ans=0; for(int i=0;i<=t;i++) { for(int j=0;j<=b;j++) { ans=max(ans,d[n][i][0][j]); } } return ans; } void add(int x,int y,int val,int time) { edge[cnt].to=y; edge[cnt].val=val; edge[cnt].time=time; edge[cnt].next=head[x]; head[x]=cnt++; } int main() { int T; int cas=1; scanf("%d",&T); while(T--) { scanf("%d%d%d%d%d%d",&n,&m,&b,&k,&r,&t); init(); for(int i=0;i<k;i++) { for(int j=1;j<=n;j++) { scanf("%d",&num[i][j]); } } for(int i=1;i<=m;i++) { int x,y,time,val; scanf("%d%d%d%d",&x,&y,&time,&val); add(x,y,val,time); } int ans=bfs(); printf("Case #%d: ",cas++); if(ans!=-1) { printf("%d\n",ans); } else { printf("Forever Alone\n"); } } return 0; }