1. 程式人生 > 實用技巧 >Ubuntu18.04.4物理安裝(雙系統)、解析度調整、windows桌面遠端xrdp訪問Ubunutu及遠端桌面解析度問題

Ubuntu18.04.4物理安裝(雙系統)、解析度調整、windows桌面遠端xrdp訪問Ubunutu及遠端桌面解析度問題

https://codeforces.com/contest/1382/problem/D

題意:定義兩個陣列的合併merge(a,b),每次將陣列a第一個元素和陣列b第一個元素中最小的那個放到陣列c中,同時刪除那個最小的元素,現在給你一個長度為2*n的排列,問是否能由兩個長度為n的數組合並而成

思路:對於長度為2*n的排列,顯然是通過一段一段合併得到的,例如(3,2,6,1,5,7,8,4),找到3後面比他大的第一個數6,6後面比他大的第一個數7,7後面比他大的第一個數8,應該分為(3,2),(6,1,5),(7),(8,4)這四段,然後將這四段進行分配,判斷能夠組成兩個長度為n的陣列,用01揹包判斷(揹包容量為n,物品的容量和價值都為每一段的長度),判斷最後的最大價值是否為n即可

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <vector>
 6 
 7 using namespace std;
 8 
 9 typedef long long ll;
10 
11 const int N = 4010;
12 const int INF = 0x3f3f3f3f;
13 
14 int T, n, cnt, a[N], d[N], dp[N];
15 vector<int
> p; 16 17 int main() 18 { 19 // freopen("in.txt", "r", stdin); 20 // freopen("out.txt", "w", stdout); 21 scanf("%d", &T); 22 while (T--) { 23 cnt = 0; 24 p.clear(); 25 scanf("%d", &n); 26 for (int i = 1; i <= 2 * n; i++) scanf("%d", &a[i]);
27 int imax = 0; 28 for (int i = 1; i <= 2 * n; i++) { 29 if (a[i] < imax) continue; 30 imax = a[i]; 31 p.push_back(i); 32 // printf("i:%d\n",i); 33 } 34 p.push_back(2 * n + 1); 35 for (int i = 1; i < p.size(); i++) 36 d[++cnt] = p[i] - p[i - 1]; 37 for (int i = 1; i <= n; i++) dp[i] = -INF; 38 for (int i = 1; i <= cnt; i++) 39 for (int k = n; k >= d[i]; k--) 40 dp[k] = max(dp[k], dp[k - d[i]] + d[i]); 41 printf(n == dp[n] ? "YES\n" : "NO\n"); 42 // printf("dp:%d\n",dp[n]); 43 } 44 return 0; 45 }
View Code