[codeforces 1382D] Unmerge 寻找连续非递增序列+01背包

Codeforces Round #658 (Div. 2)   参与排名人数14674

[codeforces 1382D]   Unmerge  寻找连续非递增序列+01背包

总目录详见https://blog.csdn.net/mrcrack/article/details/103564004

在线测评地址http://codeforces.com/contest/1382/problem/D

Problem Lang Verdict Time Memory
D - Unmerge GNU C++17 Accepted 46 ms 3900 KB

题目大意:合并两个数组,需按递归的方式,给出一个包含2*n个元素的排列数的数组,问,是否是由两个包含n个元素的数组合并而来,若是,输出YES,否则,输出NO.

样例模拟如下:

2
2 3 1 4

模拟发现(3 1)必须摆放到同一个数组中
对应两个数组如下
2 4
3 1

2
3 1 2 4

模拟发现(3 2 1)必须摆放到同一个数组中
找不到对应两个数组

4
3 2 6 1 5 7 8 4


模拟发现(3 2)必须摆放到同一个数组中
模拟发现(6 1 5)必须摆放到同一个数组中
模拟发现(8 4)必须摆放到同一个数组中
对应两个数组如下
3 2 8 4
6 1 5 7

3
1 2 3 4 5 6
对应两个数组如下
1 2 3
4 5 6

4
6 1 3 7 4 5 8 2
模拟发现(6 1 3)必须摆放到同一个数组中
模拟发现(7 4 5)必须摆放到同一个数组中
模拟发现(8 )必须摆放到同一个数组中
找不到对应两个数组


6
4 3 2 5 1 11 9 12 8 6 10 7
模拟发现(4 3 2)必须摆放到同一个数组中
模拟发现(5 1)必须摆放到同一个数组中
模拟发现(11 9)必须摆放到同一个数组中
模拟发现(12 8 6)必须摆放到同一个数组中
模拟发现(10 7)必须摆放到同一个数组中
找不到对应两个数组

如何处理每个数组选择的元素个数的组团,这是01背包最擅长的。

AC代码如下:

#include 
#include 
#define maxn 2010
using namespace std;
int a[maxn<<1],len[maxn<<1],dp[maxn];
int main(){
	int t,n,i,j,cnt,num,mx;
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		for(i=1;i<=2*n;i++)scanf("%d",&a[i]);
		for(i=0;i<=n;i++)dp[i]=0;
		cnt=1,num=1,len[cnt]=1,mx=a[1];
		for(i=2;i<=2*n;i++)
			if(a[i]>mx)len[cnt++]=num,num=1,mx=a[i];//统计连续的非递增序列中元素个数,这些元素须摆在同一数组中
			else num++;//a[i]<=mx
		len[cnt++]=num;//边界处理
		for(i=1;i=len[i];j--)
				dp[j]=max(dp[j],dp[j-len[i]]+len[i]);
		if(dp[n]==n)printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}

后记:处理该题时,寻找连续非递增序列,已经发现,但再进一步处理时,没有考虑到用01背包的方式来处理。

类似题目:

AtCoder Beginner Contest 159 F Knapsack for All Segments 01背包+一维数组+排列组合

你可能感兴趣的:(codeforces)