标签:取数游戏 比较 code 避免 ems opened 游戏 size 方程式
区间DP。
可以看出每行互不影响,所以每次区间DP求出本行最大值,ans即加上每一行最大值。
转移方程式:f[L][R]=max(num[L]*p[k]+dp(L+1,R),dp(L,R-1)+num[R]*p[k])
#include<bits/stdc++.h> #define For(i,l,r) for(int i=l;i<=r;i++) #define lll __int128 #define ll long long using namespace std; const int M=81; int n,m,num[M]; lll ans,p[M],f[M][M]; inline ll read(){ ll f=1,sum=0; char ch=getchar(); while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();} while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();} return f*sum; } inline void write(lll x){ if(x<0) putchar(‘-‘),x=-x; if(x>9) write(x/10); putchar(x%10+‘0‘); } inline lll dp(int l,int r){ if(f[l][r]!=-1) return f[l][r]; if(r-l>=1) f[l][r]=max(num[l]*p[m-r+l]+dp(l+1,r),dp(l,r-1)+num[r]*p[m-r+l]); else f[l][r]=num[l]*p[m-r+l]; return f[l][r]; } int main(){ n=read(),m=read(); p[0]=1; For(i,1,m) p[i]=p[i-1]*2; For(i,1,n){ For(j,1,m) num[j]=read(); memset(f,-1,sizeof(f)); ans+=dp(1,m); } write(ans); return 0; }
#蒟蒻看再久都不知从何下手,神犇一眼秒说是基础递推#
一个比较有趣的dp方程,f[i][j][p][k]中(i,j)表示所处位置,p代表魔夜差值,k代表最后一步是小a还是小uim走。a[i][j]即所处位置魔液值。ans加上f[i][j][0][1]。
转移方程式很好想(+k是避免减出负数):
f[i][j][p][0]+=f[i-1][j][(p-a[i][j]+k)%k][1]
f[i][j][p][0]+=f[i][j-1][(p-a[i][j]+k)%k][1]
f[i][j][p][1]+=f[i-1][j][(p+a[i][j])%k][0]
f[i][j][p][1]+=f[i][j-1][(p+a[i][j])%k][0]
四维数组注意算空间内存。两次30分因为写成+=,别缩写啦!!
标签:取数游戏 比较 code 避免 ems opened 游戏 size 方程式
原文地址:https://www.cnblogs.com/jian-song/p/11624867.html