1. 程式人生 > 實用技巧 >cf1382D---思維+01揹包

cf1382D---思維+01揹包

題目連結:https://codeforces.com/contest/1382/problem/D

簡單題意:給定1到2*n的一個排列,問是否能由兩個長度為n的陣列歸併得到

首先注意到,原來2*n的排列中,一個數和右邊連續的所有比它小的數,是必須在一個數組裡的。這樣就可以把原2*n排列分段。比如樣例中 6 1 3|7 4 5|8 2各個段的長度就是3 3 2。如果有一些段的長度和為n,那麼把它們放到一個數組裡就可以了(然後將另外的段放到另一個數組,容易發現這樣是滿足的)。是否存在一些段長度和為n可以用01揹包判斷

#include<bits/stdc++.h>
using namespace std;

const int maxn=4000+10;
int t,n,i,j,k,cnt,a[maxn],c[maxn],dp[maxn];

int main(){
	scanf("%d",&t);
	while (t--){
	  scanf("%d",&n);
	  for (i=1;i<=2*n;i++) scanf("%d",&a[i]);
	  a[2*n+1]=1e9; i=1;j=2; cnt=0;
	  while (i<=2*n){ //* 求出每段長度 
	  	while (a[j]<a[i]) j++;
	  	c[++cnt]=j-i;
	  	i=j; j=i+1;
	  }
	  memset(dp,0,sizeof(dp)); dp[0]=1;
	  for (i=1;i<=cnt;i++) //01揹包 
	    for (j=n;j>=c[i];j--)
	      if (dp[j-c[i]]) dp[j]=1;
	  if (dp[n]) puts("YES\n"); else puts("NO\n");
	}
	return 0;
}