在k个平行空间中,n个点,由m条有向边连接起来,每条边有一个时间花费和金钱花费,同时,在每个点上,可以跳转到(ki+1)%k 的空间里,不同空间的边权值不变。另外,在每到达某个空间的某个顶点时,可以买一包盐,卖一包盐,或者什么也不做,买卖的时间不考虑。相同的顶点在不同的空间中盐的价格也不一定相同..现在给定顶点数n,边数m,盐的最大携带量b,空间数k,初始的金钱r,规定的时间t,问怎么走可以在t时间内从1到达n,并且使到达n时身上的金钱尽可能大。初始时身上一包盐也没有,并且只有在空间0的时候,才能访问顶点1和n,并且一旦到达顶点n,这个过程就要结束......
很绕口的题目= =....读清楚题意的话首先很容易想到spfa..现场赛的时候估计时间空间给的比较宽松,的确有队伍用spfa过了,但也有被卡常数的..hdoj上spfa估计就不太好过了..时间卡的太近。我是直接写了一个bfs,记录dp【id】【b】【k】【t】,表示在顶点id,身上有b包盐,空间k,还剩t分钟的时间时,身上最多能有多少钱,刚开始写spfa,需要反复的进出队列,所以很悲剧的TLE了。要控制每个状态进出队列一次,又发现有些状态明明可以取得一个更大的值-,但它之前已经被一个小的值占用了-然后我就直接把队列换成了个优先队列,按剩余时间的大小从大到下向下扩展状态,这样就可以保证bfs进行的时候,一定是按时间来一层一层扩展的,并且可以保证在从当前状态开始扩展之前,当前的状态一定是最优的。另外还有一个小坑-不知道是我别的地方写毁了还是怎么回事-..每次跳转空间或者是走到新的顶点时,如果目标点的dp值需要更新,显然需要根据更新后的值来扩展买,卖,不买不卖三种新的状态,但是如果目标点的值不需要更新,我依然需要按这个“不是目标状态最优的值”来扩展买,卖,不买不卖三种状态。举个例子 当前状态如果是2 2 0 25 下一步可以到达 2 2 1 24 然后卖掉一包盐扩展出 2 1 1 24,因为已经卖了一包盐了,他不可以再扩展出2 0 1 24.然后到达2 1 0 25的时候,下一步到达2 1 1 24发现这么走到2 1 1 24没有它当前的钱多,但这个不是最优的状态却可以继续扩展出2 0 1 24这个状态的最优值,所以在这就算得到的不是最优的钱数,我们依然需要往下扩展一下...然后就AC了......
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <memory.h>
#include <cmath>
#include <queue>
#include <stack>
#include <string>
#include <cstring>
using namespace std;
typedef long long ll;
bool vis[105][6][6][202];
int g[105][6][6][202];
int n,m,b,r,k,t,numtt;
int trade[105][6];
inline int getint() {
char c = getchar();
int t = 0;
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') {
t = t * 10 + c - '0';
c = getchar();
}
return t;
}
struct Edge
{
int v,wt,wm,next;
}edge[202];
int ge[105];
struct sta
{
int id,b,k,t;
sta(){};
sta(int x1,int x2,int x3,int x4)
{
id=x1;
b=x2;
k=x3;
t=x4;
}
// bool operator>(const sta& s1)const
// {
//
// return t>s1.t;
// }
bool operator<(const sta& s1)const
{
return t<s1.t;
}
};
int en;
void bfs()
{
memset(vis,false,sizeof vis);
memset(g,-1,sizeof g);
priority_queue<sta> q;
vis[1][0][0][t]=true;
g[1][0][0][t]=r;
q.push(sta(1,0,0,t));
while(!q.empty())
{
sta now=q.top();
sta tmp=now;
q.pop();
// vis[now.id][now.b][now.k][now.t]=false;
int tid=now.id,tb=now.b,tk=now.k,tt=now.t;
int fee;
if (tt>0 && tid!=n && tid!=1)
{
tk++;
if (tk==k) tk=0;
tt--;
if (g[tid][tb][tk][tt]<g[now.id][now.b][now.k][now.t])
{
g[tid][tb][tk][tt]=g[now.id][now.b][now.k][now.t];
if (!vis[tid][tb][tk][tt])
{
q.push(sta(tid,tb,tk,tt));
vis[tid][tb][tk][tt]=true;
}
}
int ttk=tk,ttid=tid,ttb=tb,ttt=tt;
fee=g[now.id][now.b][now.k][now.t];
if (fee>=trade[ttid][ttk] && ttb<b)
{
fee-=trade[ttid][ttk];
ttb++;
if (g[ttid][ttb][ttk][ttt]<fee)
{
g[ttid][ttb][ttk][ttt]=fee;
if (!vis[ttid][ttb][ttk][ttt])
{
q.push(sta(ttid,ttb,ttk,ttt));
vis[ttid][ttb][ttk][ttt]=true;
}
}
}
ttk=tk; ttid=tid; ttb=tb; ttt=tt;
fee=g[now.id][now.b][now.k][now.t];
if (ttb>0)
{
fee+=trade[ttid][ttk];
ttb--;
if (g[ttid][ttb][ttk][ttt]<fee)
{
g[ttid][ttb][ttk][ttt]=fee;
if (!vis[ttid][ttb][ttk][ttt])
{
q.push(sta(ttid,ttb,ttk,ttt));
vis[ttid][ttb][ttk][ttt]=true;
}
}
}
}
for (int j=ge[now.id]; j!=-1; j=edge[j].next)
{
tid=now.id;
tb=now.b;
tk=now.k;
tt=now.t;
fee=g[tid][tb][tk][tt];
int u=now.id;
int v;
if (fee>=edge[j].wm && tt>=edge[j].wt)
{
v=edge[j].v;
if ((v==1 || v==n) && tk!=0) continue;
fee-=edge[j].wm;
tt-=edge[j].wt;
if (g[v][tb][tk][tt]<fee)
{
g[v][tb][tk][tt]=fee;
if (!vis[v][tb][tk][tt] && v!=n)
{
q.push(sta(v,tb,tk,tt));
vis[v][tb][tk][tt]=true;
}
}
if (v!=n && v!=1)
{
int ttk=tk,ttid=v,ttb=tb,ttt=tt;
fee=g[now.id][now.b][now.k][now.t]-edge[j].wm;
if (fee>=trade[v][tk] && ttb<b)
{
fee-=trade[v][tk];
ttb++;
if (g[ttid][ttb][ttk][ttt]<fee)
{
g[ttid][ttb][ttk][ttt]=fee;
if (!vis[ttid][ttb][ttk][ttt])
{
q.push(sta(ttid,ttb,ttk,ttt));
vis[ttid][ttb][ttk][ttt]=true;
}
}
}
ttb=tb;
fee=g[now.id][now.b][now.k][now.t]-edge[j].wm;
if (ttb>0)
{
fee+=trade[v][tk];
ttb--;
if (g[v][ttb][ttk][ttt]<fee)
{
g[v][ttb][ttk][ttt]=fee;
if (!vis[v][ttb][ttk][ttt])
{
q.push(sta(v,ttb,ttk,ttt));
vis[v][ttb][ttk][ttt]=true;
}
}
}
}
}
}
}
}
int main()
{
// freopen("in.txt","r",stdin);
// scanf("%d",&numtt);
numtt=getint();
for (int ii=1; ii<=numtt; ii++)
{
memset(ge,-1,sizeof ge);
// scanf("%d%d%d%d%d%d",&n,&m,&b,&k,&r,&t);
n=getint(); m=getint();b=getint(); k=getint(); r=getint(); t=getint();
for (int i=0; i<k; i++)
for (int j=1; j<=n; j++)
// scanf("%d",&trade[j][i]);
trade[j][i]=getint();
int x,y,z1,z2;
en=0;
for (int i=1; i<=m; i++)
{
// scanf("%d%d%d%d",&x,&y,&z1,&z2);
x=getint(); y=getint(); z1=getint(); z2=getint();
edge[en].v=y;
edge[en].wt=z1;
edge[en].wm=z2;
edge[en].next=ge[x];
ge[x]=en;
en++;
}
bfs();
int ans=-1;
printf("Case #%d: ",ii);
for (int i=0; i<=t; i++)
for (int j=0; j<=b; j++)
ans=max(ans,g[n][j][0][i]);
if (ans>=0) printf("%d\n",ans);
else puts("Forever Alone");
}
return 0;
}