hdu 5693 D Game(区间DP)
题目链接:hdu 5693 D Game
题意:
首先度度熊拥有一个公差集合{D},然后它依次写下N个数字排成一行。游戏规则很简单:
1. 在当前剩下的有序数组中选择X(X≥2) 个连续数字;
2. 检查1选择的X个数字是否构成等差数列,且公差 d∈{D};
3. 如果2满足,可以在数组中删除这X个数字;
4. 重复 1−3 步,直到无法删除更多数字。
问最多能删掉多少个数字?
题解:
考虑区间DP,设f[i][j]表示数从i到j能否删除,由于等差数列性质,只需要单独考虑2个和3个数字的情况,其他都能由这两种情况组成。
最后再设dp[i]表示前i个最多能删除多少个,然后dp[i]=max(dp[i],dp[i-1]+j-i+1)。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 #define mst(a,b) memset(a,b,sizeof(a)) 3 #define F(i,a,b) for(int i=a;i<=b;++i) 4 using namespace std; 5 typedef long long ll; 6 7 const int N=307; 8 int t,n,m,a[N],x,dp[N]; 9 map<int,int>cnt; 10 bool f[N][N]; 11 12 int main(){ 13 scanf("%d",&t); 14 while(t--) 15 { 16 scanf("%d%d",&n,&m); 17 F(i,1,n)scanf("%d",a+i); 18 mst(f,0),cnt.clear(); 19 F(i,1,m)scanf("%d",&x),cnt[x]=1; 20 F(l,2,n)F(i,1,n-l+1) 21 { 22 int j=i+l-1; 23 if(l==2&&cnt[a[i+1]-a[i]])f[i][j]=1; 24 else if(l==3&&2*a[i+1]==a[i]+a[i+2]&&cnt[a[i+1]-a[i]])f[i][j]=1; 25 else 26 { 27 if(cnt[a[j]-a[i]]&&f[i+1][j-1])f[i][j]=1; 28 F(k,i+1,j-1)f[i][j]|=f[i][k]&f[k+1][j]; 29 } 30 } 31 F(j,1,n) 32 { 33 dp[j]=dp[j-1]; 34 F(i,1,j)if(f[i][j])dp[j]=max(dp[j],dp[i-1]+j-i+1); 35 } 36 printf("%d\n",dp[n]); 37 } 38 return 0; 39 }