对 100%的数据,n≥1,C≥0,W≥0,T≥1,s i,j,k ≥0
分析:
根据题意可以很直白的得出状态f[T][x][y][k]表示T秒,(x,y),总共用了k次闪现。加个滚动数组优化一维。因为走的转移为O(1),而闪现的转移:
f[T][x][y][k]=max(f[T][nx][ny][k-use]),(nx,ny)为闪现use次后的坐标,需要O(C)的时间,转移,这是我们优化的重点,我们必须将其优化为O(1)才能过,怎么办?O(1)->单调队列维护转移。
我们画一个图,以向左闪现为例:
f[T][x][y][k]=max(f[T][x][y+2][k-1],f[T][x][y+2*2][k-1*2],f[T][x][y+2*3][k-1*3].....)
我们可以维护一个单调队列q[head]=max(f[T][x][y+2][k-1]....),并转移到f[T][x][y][k]后,将其加入队列,以便维护下一个f[T][x][y-2][k+1]以O(1)转移。
参考程序:
#include
#include
#include
using namespace std;
const int maxn=160;
int a[maxn][maxn],vis[maxn][maxn];
int f[2][160][110][110];
int direction[4][2]={
{1,0},{0,1},{-1,0},{0,-1},
};
int n,C,W,T,res=0,cnt=0,tag=0,head,tail;
int q[maxn*maxn],qc[maxn*maxn];
const int inf=1e9+7;
bool ok(int x,int y){
if (0=q[tail])sum+=qc[tail--];
q[++tail]=x;qc[tail]=sum;
if (++cnt>C)if (--qc[head]==0)head++;
}
int main(){
freopen("coin.in","r",stdin);
freopen("coin.out","w",stdout);
scanf("%d%d%d%d",&n,&C,&W,&T);
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
scanf("%d",&f[0][0][i][j]);
for (int K=1;K0;y--)
for (int j=0;j<=W;j++)
if (vis[y][j]!=tag){
clear();
int yy=y,jj=j;
while (yy>0 && jj<=W){
vis[yy][jj]=tag;
f[p][jj][x][yy]=max(f[p][jj][x][yy],q[head]);
push(f[t][jj][x][yy]);
yy-=2;
jj++;
}
}
}
for (int y=1;y<=n;y++){
++tag;
for (int x=1;x<=n;x++)
for (int j=0;j<=W;j++)
if (vis[x][j]!=tag){
clear();
int xx=x,jj=j;
while (xx<=n && jj<=W){
vis[xx][jj]=tag;
f[p][jj][xx][y]=max(f[p][jj][xx][y],q[head]);
push(f[t][jj][xx][y]);
xx+=2;
jj++;
}
}
++tag;
for (int x=n;x>0;x--)
for (int j=0;j<=W;j++)
if (vis[x][j]!=tag){
clear();
int xx=x,jj=j;
while (xx>0 && jj<=W){
vis[xx][jj]=tag;
f[p][jj][xx][y]=max(f[p][jj][xx][y],q[head]);
push(f[t][jj][xx][y]);
xx-=2;
jj++;
}
}
}
for (int x=1;x<=n;x++)
for (int y=1;y<=n;y++)
for (int j=0;j<=W;j++){
f[p][j][x][y]=max(f[p][j][x][y],f[t][j][x][y]);
for (int k=0;k<5;k++){
int nx=x+direction[k][0];
int ny=y+direction[k][1];
if (ok(nx,ny))f[p][j][x][y]=max(f[p][j][x][y],f[t][j][nx][ny]);
}
}
for (int x=1;x<=n;x++)
for (int y=1;y<=n;y++)
for (int j=0;j<=W;j++)
f[p][j][x][y]+=a[x][y];
}
int p=(T-1)&1;
for (int x=1;x<=n;x++)
for (int y=1;y<=n;y++)
for (int j=0;j<=W;j++)
res=max(res,f[p][j][x][y]);
printf("%d",res);
return 0;
}