洛谷3257 [JLOI2014]天天酷跑(DP)(記憶化搜尋)
阿新 • • 發佈:2018-11-11
題目
每次往上跳或往下掉或持平……(具體看題目吧),使路徑上的權值和最大。
題解
記憶化搜尋
設f[i][j][t]表示從出發點到(x,y)這個位置(不含這個位置,即減掉ma[x][y])還可以跳t次的最大權值和。
轉移方程
,其中w表示這一路上的點權和。
下面說說前輩繞的彎路,
注意一下輸入,第一行是底~
再注意一點,回到底後可以重置可跳次數~
考慮細緻一點,這題還是不難的~
程式碼
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int inf=(1<<30)-1; const int maxn=100010,maxm=25; int n,m,cost1,cost2; int ma[maxn][maxm]; int h,c; int f[maxn][maxm][6]; int dfs(int x,int y,int t)//在(x,y)還能跳t次 { if(y<1||y>m || t<0) return -inf; if(~f[x][y][t]) return f[x][y][t]; if(ma[x][y]==-1) return f[x][y][t]=-inf; if(x>=n) return f[x][y][t]=0; int re; /*if(y>1) re=dfs(x+1,y-1,t)+ma[x+1][y-1];//debug*/ if(y>2) re=dfs(x+1,y-1,t)+ma[x+1][y-1];//debug else if(y==2) re=dfs(x+1,y-1,c)+ma[x+1][y-1]; else re=dfs(x+1,y,c)+ma[x+1][y];//re=max(re, dfs(x+1,y,t) ); int sum=0; for(int i=1;i<=h;i++) sum+=ma[x+i][y+i]; re=max(re, dfs(x+h,y+h,t-1)+sum); f[x][y][t]=re; // printf("(%d %d %d %d)\n",x,y,t,f[x][y][t]); return re; } int main() { scanf("%d%d%d%d",&n,&m,&cost1,&cost2); for(int i=1;i<=m;i++)//debug輸入不要倒序 //i要倒序輸入 for(int j=1;j<=n;j++) scanf("%d",&ma[j][i]);//debug ma[j][i] int ans=-1,ansc,ansh; for(c=1;c<=5;c++)//最大連跳c次 { for(h=1;h*c<m;h++)//跳躍高度為h { memset(f,-1,sizeof(f)); // puts("--------------------------------------------"); int tmp=dfs(0,1,c)-cost1*(h-1)-cost2*(c-1); if(tmp>ans) { ans=tmp; ansc=c;ansh=h; } } } if(~ans) printf("%d %d %d\n",ans,ansc,ansh); else puts("mission failed"); return 0; }