bzoj2708木偶(dp)

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。

發佈了59 篇原創文章 · 獲贊 1 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章