Codeforces Round #658 (Div. 2) D. Unmerge ###K ###K //K

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

题意:给一段长为2n 的排列方式(permutation) 问 能否找到对应的 两段n 组成的 序列  构成这段排列方式

当a[1]<b[1]时候  将a[1] 取出,然后变成(a[2]……a[n] 和b[1] ……b[n])重复操作 反之则取b[1]   取出的顺序即为得到的序列的顺序

思路:手动模拟一下 就可以发现 后面的小的数必须跟在前面的大的数后面, 这是相对固定的顺序  如 3 2 6 1 5 7 8 4 

3 2  为一组  6 1 5 为一组 7 为一组  8 4为一组  分成了四组   那么我们只需要看这些组能不能拼成一个n的序列就知道是否满足了 

 那么把长度当作重量也当作价值,跑一遍01背包  看dp[n]是否为n 即可  

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define ull unsigned long long
 5 #define pb push_back
 6 const int maxn=1e5+10;
 7 const int mod=1e9+7;
 8 int p[5005];
 9 int dp[2005];
10 
11 int main()
12 {
13     ios::sync_with_stdio(false);
14     cin.tie(0);
15     int t;
16     cin>>t;
17     while(t--)
18     {
19         int n;
20         cin>>n;
21         memset(dp,0,sizeof(dp));
22         vector<int>a;
23         for(int i=1;i<=n*2;i++)
24         {
25             cin>>p[i];
26         }
27         int cnt=p[1];
28         int sum=1;
29         for(int i=2;i<=n*2;i++)
30         {
31             if(p[i]<cnt)
32             {
33                 sum++;
34             }
35             else
36             {
37                 if(sum)
38                     a.pb(sum);
39                 sum=1;
40                 cnt=p[i];
41             }
42         }
43         if(sum)
44             a.pb(sum);
45         int len=a.size();
46         for(int i=0;i<len;i++)
47         {
48             for(int j=n;j>=0;j--)
49             {
50                 if(j>=a[i])
51                 {
52                     dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
53                 }
54             }
55         }
56         if(dp[n]==n)
57         {
58             cout<<"YES"<<'\n';
59         }
60         else
61             cout<<"NO"<<'\n';
62 
63     }
64 
65 
66 
67 }
View Code

 

posted @ 2020-08-02 13:23  canwinfor  阅读(119)  评论(0)    收藏  举报