dp问题。
设f [ i ]表示前 i 个数里最多能扔多少个,f [ i ]=max(f [ i ], f [ j ]+find(j+1, i ));
这里的find表示从第j+1个数到第i个数最多扔掉几个,采用枚举扔的个数,若在扔的一堆中能互相配对,在没扔的一堆中任意两个不能配对,就是可行的。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int n;
int a[2000];
int cmp(int a,int b)
{
return a<b;
}
int f[2000];
int find(int st,int to)
{
if(a[to]-a[st]<=1)
{
return 0;
}
for(int i=1;i<=to-st+1;i++)
{
for(int j=st+i;j<=to;j++)
{
if(abs(a[j]-a[j-i])>1)
{
return i-1;
}
}
if(abs(a[st+i-1]-a[to-i+1])<=1)
{
return i-1;
}
}
return to-st+1;
}
int main()
{
// freopen("puppet,in","r",stdin);
// freopen("puppet.out","w",stdout);
while(scanf("%d",&n)!=EOF)
{
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
sort(a+1,a+1+n,cmp);
f[1]=0;
for(int i=2;i<=n;i++)
{
for(int j=0;j<i;j++)
{
f[i]=max(f[j]+find(j+1,i),f[i]);
}
}
printf("%d\n",f[n]);
}
return 0;
}
以下摘自他人博客:
其实dp很难逃出3种思路:
1、一维线性dp:每次考虑i时,选择最优子问题要么在i-1,要么在1...i-1里;
2、二维线性dp:考虑(i,j)子问题时,选择最优子问题要么在(i+1,j)、(i,j-1),要么在i<= k <=j,在k里;
3、树形dp:考虑i节点最优时,选择子节点最优,一般融合了01揹包dp的双重dp。