hdu 6199 dp

题意:巨毒。。实际上就是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
",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
", max(dp[1][1],dp[1][2]));
	}
	return 0;
}



原文地址:https://www.cnblogs.com/zhangxianlong/p/10672480.html