Codeforces Round #658 (Div. 2) D. Unmerge (01背包)

题目链接:https://codeforces.ml/contest/1382/problem/D

题意:定义两个数组的合并merge(a,b),每次将数组a第一个元素和数组b第一个元素中最小的那个放到数组c中,同时删除那个最小的元素,现在给你一个长度为2*n的排列,问是否能由两个长度为n的数组合并而成。

题解:通过观察可以发现这一段序列由若干个子段组成,例如3 1 2 4可以由3 1 2 和 4组成,其分法是以最大值为分割点,可以简单的证明一下,若将一段中小的放到另一个数组b中,则该小的数必然排在大的数字前,也就是分解成3 1 和 2 4那么2一定会排在3的前面。得到这个结论后问题就转化成有若干段,问是否能组成长度为n的一段,因此跑一遍01背包即可,体积和价值都是某一段的长度。

代码:

#include
using namespace std;
typedef long long ll;
const int maxn=5000;
int f[maxn],a[maxn];
typedef struct{
	int w,v;
}goods;
goods g[maxn];

int main()
{
	int T;cin>>T;
	while(T--){
		int n;cin>>n;int cnt=0;
		for(int i=1;i<=2*n;i++) cin>>a[i];
		memset(f,0,sizeof(f));
		int mx=a[1];int num=1;
		for(int i=2;i<=2*n;i++){
			if(a[i]=g[i].w;j--)
				f[j]=max(f[j],f[j-g[i].w]+g[i].v);
		}
		if(f[n]==n) cout<<"YES"<

 

你可能感兴趣的:(codeforces)