hdu 5639 D Game 区间dp

本文介绍了一种名为DGame的游戏,玩家需要通过识别等差数列来删除数字,旨在找到最优策略以最大化删除数字的数量。文章详细解释了游戏规则,并提供了一个具体的实现代码示例。

D Game

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 298    Accepted Submission(s): 106


Problem Description
众所周知,度度熊喜欢的字符只有两个:B 和D。

今天,它发明了一个游戏:D游戏。

度度熊的英文并不是很高明,所以这里的D,没什么高深的含义,只是代指等差数列[(等差数列百科)](http://baike.baidu.com/view/62268.htm)中的公差D。

这个游戏是这样的,首先度度熊拥有一个公差集合 {D} ,然后它依次写下 N 个数字排成一行。游戏规则很简单:

1. 在当前剩下的有序数组中选择 X(X2)  个连续数字;

2. 检查 1 选择的 X 个数字是否构成等差数列,且公差  d{D}

3. 如果 2 满足,可以在数组中删除这 X 个数字;

4. 重复  13  步,直到无法删除更多数字。

度度熊最多能删掉多少个数字,如果它足够聪明的话?
 

Input
第一行一个整数 T ,表示 T(1T100)  组数据。

每组数据以两个整数  N M  开始 。接着的一行包括  N  个整数,表示排成一行的有序数组  Ai 。接下来的一行是  M  个整数,即给定的公差集合  Di

1N,M300

1 000 000 000Ai,Di1 000 000 000
 

Output
对于每组数据,输出最多能删掉的数字 。
 

Sample Input
  
3 3 1 1 2 3 1 3 2 1 2 4 1 2 4 2 1 3 4 3 1 2
 

Sample Output
  
3 2 4
 

Source
 

Recommend
wange2014   |   We have carefully selected several similar problems for you:   5701  5700  5699  5698  5697 
 



对于删除长度为k的连续个数那么一定可以转化为删除若干个2个数和若干个3个数

那么我们可以先预处理出任意两个数是否成等差即是否在连续的时候可删除

然后我们枚举区间长度 在这区间内枚举删除长度为2和长度为3的情况

例如 区间i~j全都可以删除满足条件 区间i+1~j-1可以全部删除 且 对于a【j】-a【i】是一个等差

ACcode:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>
#define maxn 302
using namespace std;
int dp[maxn][maxn],a[maxn],b,d[maxn];
bool can[maxn][maxn];
int loop,n,m;
int main(){
    ios::sync_with_stdio(false);
    cin>>loop;
    while(loop--){
        cin>>n>>m;
        int tot=0;
        for(int i=1;i<=n;++i){
                cin>>a[i];
                for(int j=1;j<=n;++j)
                    dp[i][j]=can[i][j]=0;
        }
        for(;m--;){
            cin>>b;
            for(int i=1;i<n;++i)
            for(int j=i+1;j<=n;++j)
                if(a[j]-a[i]==b)can[i][j]=1;
        }
        for(int l=2;l<=n;++l){
            for(int i=1;i+l-1<=n;++i){
                int j=l+i-1;
                dp[i][j]=max(dp[i+1][j],dp[i][j-1]);
                if(can[i][j]&&dp[i+1][j-1]==j-i-1)dp[i][j]=max(dp[i][j],dp[i+1][j-1]+2);
                for(int k=i+1;k<j;++k){
                    dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]);
                    if(can[i][k]&&dp[i+1][k-1]==(k-i-1))  dp[i][j]=max(dp[i][j],dp[i+1][k-1]+dp[k+1][j]+2);
                    if(can[k][j]&&dp[k+1][j-1]==(j-k-1))  dp[i][j]=max(dp[i][j],dp[i][k-1]+dp[k+1][j-1]+2);
                    if(can[i][k]&&can[k][j]&&a[k]-a[i]==a[j]-a[k]&&dp[i+1][k-1]==(k-i-1)&&dp[k+1][j-1]==(j-k-1)) dp[i][j]=max(dp[i][j],j-i+1);
                }
            }
        }
        cout<<dp[1][n]<<'\12';
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值