暴力DP。
dp[x1][y1][x2][y2][t]表示,第一个人在(X1,Y1),第二个人在(X2,Y2),时间为t的时候获得的最大价值。
时间复杂度o(t*n*m*n*m*5*5).
什么都不优化跑了4600ms,差点超时,剪了点枝,2500ms跑过。
空间复杂度是可以优化的,dp[x1][y1][x2][y2][t]只与t-1时刻的有关,所以dp数组最后一维可以开成2,用滚动数组做。
#include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<algorithm> using namespace std; int dp[11][11][11][11][205]; char s[11][11]; int val[11][11][205]; int n,m,p; int dir[5][2]; int top; void init() { top=0; dir[0][0]=0;dir[0][1]=0; dir[1][0]=0;dir[1][1]=1; dir[2][0]=0;dir[2][1]=-1; dir[3][0]=1;dir[3][1]=0; dir[4][0]=-1;dir[4][1]=0; memset(dp,-1,sizeof dp); memset(val,0,sizeof val); } bool P(int a,int b) { if(a>=0&&a<n&&b>=0&&b<m) return 1; return 0; } void read() { scanf("%d%d",&n,&m); for(int i=0;i<n;i++) scanf("%s",s[i]); scanf("%d",&p); for(int i=0;i<p;i++) { int t,x,y,v; scanf("%d%d%d%d",&t,&x,&y,&v); x--;y--; val[x][y][t]=val[x][y][t]+v; top=max(top,t); } } void work() { int ans=0; dp[0][0][0][0][0]=0; for(int t=1;t<=top;t++) { for(int x1=0;x1<n;x1++) { for(int y1=0;y1<m;y1++) { if(s[x1][y1]!='.') continue; for(int x2=0;x2<n;x2++) { for(int y2=0;y2<m;y2++) { if(s[x2][y2]!='.') continue; for(int d1=0;d1<5;d1++) { int new_x1=x1+dir[d1][0]; int new_y1=y1+dir[d1][1]; if(P(new_x1,new_y1)==0) continue; if(s[new_x1][new_y1]!='.') continue; for(int d2=0;d2<5;d2++) { int new_x2=x2+dir[d2][0]; int new_y2=y2+dir[d2][1]; if(P(new_x2,new_y2)==0) continue; if(s[new_x2][new_y2]!='.') continue; if(dp[new_x1][new_y1][new_x2][new_y2][t-1]==-1) continue; int sum=0; sum=dp[new_x1][new_y1][new_x2][new_y2][t-1]; if(x1==x2&&y1==y2) sum=sum+val[x1][y1][t]; else sum=sum+val[x1][y1][t]+val[x2][y2][t]; dp[x1][y1][x2][y2][t]=max(dp[x1][y1][x2][y2][t],sum); ans=max(ans,dp[x1][y1][x2][y2][t]); } } } } } } } printf("%d ",ans); } int main() { int T; scanf("%d",&T); while(T--) { init(); read(); work(); } return 0; }