D GameTime Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1148 Accepted Submission(s): 424 Problem Description 众所周知,度度熊喜欢的字符只有两个:B 和D。
Input 第一行一个整数T ,表示T(1≤T≤100) 组数据。
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 2016"百度之星" - 初赛(Astar Round2A)
Recommend wange2014 | We have carefully selected several similar problems for you: 6361 6360 6359 6358 6357 |
区间dp:子区间最优推出整个区间最优。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<map>
#include<cstring>
using namespace std;
int dp[310][310]; //dp[i][j]表示i~j这个区间的最大可删除的数字
int n,t,m,d[310]; //基本思想:>=2的数都可以由2和3组成,每次至少删除2个区间或3个区间
//分类讨论
map<int,bool> vis; //md因为这是下标法,等差d<=10^9,开数组的话就爆了,用map离散化,省空间
int a[310];
int main()
{
int i,k;
int l,r,len;
scanf("%d",&t);
while(t--)
{
memset(dp,0,sizeof(dp));
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
for(i=1;i<=m;i++)
{
scanf("%d",&d[i]);
vis[d[i]]=1;
}
for(i=1;i<n;i++)
//一.预处理所有长度为2和3的区间
// 1.直接找两个等差数列的区间
if(vis[a[i+1]-a[i]])
{
dp[i][i+1]=2;
}
// 2.找三个等差数列的区间
for(i=1;i<n-1;i++)
{
if(a[i]+a[i+2]==2*a[i+1]&&vis[a[i+1]-a[i]]) //额,a[i]+a[i+2]==2*a[i+1]不就是等差数列的性质
dp[i][i+2]=3; //只要一个vis,因为只要一个d啊
else
dp[i][i+2]=max(dp[i][i+1],dp[i+1][i+2]); //这也很自然
}
//找四个以上等差序列(包括四个)
//由长度为2和3的区间组成
//组成的思想:
//原本l~r这个区间并不一定是等差的
//形成两种情况:
//1. l~r都等差
//2. l~r删掉一部分等差,剩下的部分等差。
// 这两种情况的处理方法一样
for(len=4;len<=n;len++) //处理区间DP的两个for,长度,左,推出右
for(l=1;l<=n+1-len;l++) //len-1因为要去掉l这个长度。
{
r=l+len-1; //为什么做这下面的讨论
//基本思想:>=2的数都可以由2和3组成
//要删掉一部分等差,这部分等差的长度一定是2或3
//长度又是>=4的
//以长度为4,5为特例展开讨论
//形成以下两种情况
//左右各成为等差序列,中间是等差序列
if(dp[l+1][r-1]==len-2&&vis[a[r]-a[l]])
dp[l][r]=len;
if(dp[l+1][r-2]==len-3&&vis[a[r]-a[r-1]]&&a[l]+a[r]==2*a[r-1]) //中间是等差序列,左右两端可以拼成等差序列
dp[l][r]=len;
if(dp[l+2][r-1]==len-3&&vis[a[l+1]-a[l]]&&a[l]+a[r]==2*a[l+1])
dp[l][r]=len;
for(k=l;k<r;k++) //区间长度为4只进行第一个if 区间长度>=5三个if
//区间为4左取两个,右取两个,可用区间dp,dp出来所以不需要讨论
//想要再次强调区间dp的k<r
dp[l][r]=max(dp[l][k]+dp[k+1][r],dp[l][r]);
}
printf("%d\n",dp[1][n]);
for(i=1;i<=m;i++)
vis[d[i]]=0;
}
return 0;
}