因为数据较小,可以考虑搜索。
主要的维度为当前位置p,当前消耗时间t,当前持有的盐b,当前所在宇宙k。
最大状态数为100*200*5*6,如果直接用bfs爆搜,因为状态间的边权不是统一的1,那么bfs第一次更新到的点不一定是最优值,所以每个状态需要多次被更新,且多次进入队列,会超时。
但有了时间这一维度,就产生了不同,加入队列的节点,按t值小的先出队列,那么每个节点出来之后就不会被再更新,原因很简单,所有在队列里和被队列里节点更新的节点,在该节点出队列以后不可能更新到该节点。这样用一个队列即可。
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
#define rep(i,n) for(int i=0;i<int(n);i++)
#define rep1(i,x,y) for(int i=x;i<=(int)y;i++)
typedef long long ll;
const int NN = 115;
const int MM = 215;
struct node{
int to,t,v;
node(){}
node(int to,int t,int v):to(to),t(t),v(v){}
};
vector<node> G[NN];
struct node2{
int p,t,b,k;
node2(){}
node2(int p,int t,int b,int k):p(p),t(t),b(b),k(k){}
bool operator<(const node2& rhs)const{
return t > rhs.t;
}
};
priority_queue<node2> Q;
int price[6][NN], N, M, B, K, R, T,d[NN][MM][6][6];
inline void update(node2 a,int v){
if(v > d[a.p][a.t][a.b][a.k]){
if(d[a.p][a.t][a.b][a.k] == -1) { Q.push(a);}
d[a.p][a.t][a.b][a.k] = v;
}
}
void bfs(){
memset(d,-1,sizeof(d));
d[1][0][0][0]=R;
Q.push(node2(1,0,0,0));
while(!Q.empty()){
node2 u = Q.top(); Q.pop();
int p = u.p, t=u.t, b=u.b,k=u.k;
int now = d[p][t][b][k];
if(p == N) continue;
rep(i,G[p].size()){
int p1 = G[p][i].to,cst=G[p][i].t,v=G[p][i].v;
if(now - v <0 || t+cst > T) continue;
if((p1 == 1 || p1 == N) && k!=0) continue;
update(node2(p1,t+cst,b,k),now-v);
if(p1 == 1 || p1 == N) continue;
if(b < B) update(node2(p1,t+cst,b+1,k),now-v-price[k][p1]);
if(b > 0) update(node2(p1,t+cst,b-1,k),now-v+price[k][p1]);
}
if(p == 1 || p == N) continue;
int nk = (k+1)%K;
if(t+1 > T) continue;
update(node2(p,t+1,b,nk),now);
if(b < B) update(node2(p,t+1,b+1,nk),now-price[nk][p]);
if(b > 0) update(node2(p,t+1,b-1,nk),now+price[nk][p]);
}
}
int main()
{
int Ta,kase=1;
scanf("%d",&Ta);
while(Ta--){
scanf("%d %d %d %d %d %d",&N, &M, &B, &K, &R, &T);
rep(i,K) rep1(j,1,N) scanf("%d",&price[i][j]);
rep1(i,1,N) G[i].clear();
rep1(j,1,M){
int x,y,t,v;
scanf("%d %d %d %d",&x,&y,&t,&v);
G[x].push_back(node(y,t,v));
}
printf("Case #%d: ",kase++);
bfs();
int ans = -1;
rep1(i,1,T)
if(ans < d[N][i][0][0])
ans = d[N][i][0][0];
if(ans == -1) printf("Forever Alone\n");
else printf("%d\n",ans);
}
return 0;
}