创世纪
这是我的第一道原创题

题解:
这道题的核心算法是:加维度的最短路+贪心

状态:\(dis[i][j][t][a]\)表示在 \(t\) 时,到达 \((i,j)\) ,当前共造\(a\)只"rat"的最小代价(所以相比平常的状态会多出两维)
表面上看到达一个点造的"rat"数是不固定的,实际上(在 \((t>=cnt*W[i][j])\) 的情况下,cnt越多,代价就越少),所以\(cnt=t/W[i][j]\),然后相当于两个相邻位置的代价就出来了,接着跑最短路即可。

解决不可以回到上一步的问题,只需要在队列里面加上两个变量表示当前的坐标,因此更新下一次时就特判不走这两个位置。
还有,这道题跑最短路的复杂度跟n,m规模无关,只跟t有关,所以你爆搜也行。

代码:

#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
const int N=105;
const int MaxT=17;
int n,m,L,T,A;
int W[N][N],f[N][N][MaxT][3*MaxT],dx[9]={0,0,1,-1,1,1,-1,-1},dy[9]={1,-1,0,0,1,-1,1,-1},inf=0x3f3f3f3f;
struct node {
	int x,y,w,t,a,lx,ly;
	bool operator<(const node &u) const{
		return w>u.w;
	} 
};
bool mark[N][N][MaxT][3*MaxT];
priority_queue<node> Q;
void DJ(int sx,int sy) {
	memset(f,0x3f,sizeof(f));
	f[sx][sy][1][0]=0;
	Q.push((node){sx,sy,W[sx][sy],1,0,0,0});
	while(!Q.empty()) {
		int ux=Q.top().x,uy=Q.top().y,t=Q.top().t,a=Q.top().a,lx=Q.top().lx,ly=Q.top().ly; Q.pop();
		if(mark[ux][uy][t][a]||a>A) continue;
//		printf("x=%d y=%d t=%d a=%d %d\n",ux,uy,t,a,f[ux][uy][t][a]);
		mark[ux][uy][t][a]=true;
		for(int d=0;d<4;d++) {
			int vx=ux+dx[d],vy=uy+dy[d];
			if(vx<1||vx>n||vy<1||vy>m||(vx==lx&&vy==ly)) continue;
			t++;
			int cnt=t/W[vx][vy];	//<=T最多是几倍 W[vx][vy]
			if( t<=T && !mark[vx][vy][t][a+cnt] && f[vx][vy][t][a+cnt] >= f[ux][uy][t-1][a] + (t-cnt*W[vx][vy]) ) {
				f[vx][vy][t][a+cnt] = f[ux][uy][t-1][a] + (t-cnt*W[vx][vy]);
				Q.push((node){vx,vy,f[vx][vy][t][a+cnt],t,a+cnt,ux,uy});
			}
			t--;
		}
	}
}
int main() {
//	freopen("1.out","w",stdout);
	scanf("%d%d%d%d%d",&n,&m,&L,&T,&A);
	for(int i=1;i<=n;i++) {
		for(int j=1;j<=m;j++) {
			scanf("%d",&W[i][j]);
		}
	}
	DJ(1,1);
	int ans=inf;
	for(int a=A;a<=A+T;a++)
	for(int t=1;t<=T;t++)
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++) {
		ans=min(f[i][j][t][a],ans);
//		printf("!x=%d y=%d t=%d a=%d: %d\n",i,j,t,a,f[i][j][t][a]);
	}
		
	if(ans==inf||ans>L) printf("Death.");
	else {
		printf("Yes.\n%d",ans);
	}
	return 0;
}