hdu 6199 dp
阿新 • • 發佈:2018-12-01
題意:巨毒。。實際上就是A,B都希望自己得到的最多。前一個人拿k個,下一個人能拿k or k+1
思路:倒著DP。。實際上兩個人是同一種策略,那麼其實一個dp陣列就可以了。。從最後一步拿k個往回推,dp[i][j]表示取第i個時候拿走包含i的j個,轉移方程dp[i][j]=sum[i+j-1]-sum[i-1]-max(dp[i+j][j],dp[i+j][j+1]) (PS,注意一下邊界的合法性判斷),轉移的時候要減去上一步的最優解。。因為每一步對手都會選擇最優策略。。
PS。這個題卡空間。。。要麼只開一個數組,要麼迴圈滾動一下
程式碼:
#include<bits/stdc++.h> #define MEM(x) memset(x,0,sizeof(x)) using namespace std; int dp[22000][205],n,sum[22010],v[22010]; int main(){ int t; scanf("%d", &t); while (t--){ scanf("%d",&n); sum[0]=0; MEM(dp);MEM(sum); for(int i=1;i<=n;++i)scanf("%d",&v[i]),sum[i]=sum[i-1]+v[i]; if(n==1){ printf("%d\n",v[1]); continue; } int lim = 200; for(int i=n;i>=1;--i){ for(int j =1;j<=lim;++j){ if(i+j-1>n) break; int sub=-2e9; dp[i][j]=sum[i+j-1]-sum[i-1]; if(i+j+j-1<=n)sub=max(dp[i+j][j],sub); if(i+j+j<=n)sub=max(dp[i+j][j+1],sub); if(sub!=-2e9) dp[i][j]-=sub; } } printf("%d\n", max(dp[1][1],dp[1][2])); } return 0; }