《题一》
原题链接:https://atcoder.jp/contests/abc271/tasks/abc271_d
翻译:
问题陈述
有N张卡片,每面写一个整数。卡片 正面写着一个整数ai,背面写着一位整数bi。
您可以选择将每张卡片的正面或背面都显示出来。
确定您是否可以放置卡片,使可见整数的总和正好等于S。如果可能,请找到卡片的位置以实现它。
如果只是问是否可以组成出来,十分好做,但是还要求方案
解决之道:
首先利用dp[i][j]:在前i张卡片中选择,能够到达数值正好为j,如果能为1,如果不能为0
然后利用反推
其实就是如果dp[i][j]==1,那么这个必然是通过dp[i-1][j-a[i].first]或dp[i-1][j-a[i].second]转移过来
必然dp[i-1][j-a[i].first]或dp[i-1][j-a[i].second]有一个为1,如果两个都为1选择其中一个即可
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 typedef pair<int, int> PII; 6 const int N = 101, S = 10001; 7 int n, s, dp[N][S]; 8 PII a[N]; 9 int main() 10 { 11 cin >> n >> s; 12 for (int i = 1; i <= n; i++) 13 { 14 int z, f; 15 scanf("%d%d", &z, &f); 16 a[i] = {z, f}; 17 } 18 dp[0][0] = 1; 19 for (int i = 1; i <= n; i++) 20 for (int j = 1; j <= s; j++) 21 { 22 if (j >= a[i].first) 23 dp[i][j] |= dp[i - 1][j - a[i].first]; 24 if (j >= a[i].second) 25 dp[i][j] |= dp[i - 1][j - a[i].second]; 26 } 27 if (dp[n][s]) 28 { 29 cout << "Yes" << endl; 30 string str = ""; 31 for (int i = n; i >= 1; i--) 32 { 33 if (s >= a[i].first && dp[i - 1][s - a[i].first]) 34 { 35 str += 'H'; 36 s -= a[i].first; 37 } 38 else if (s >= a[i].second && dp[i - 1][s - a[i].second]) 39 { 40 str += 'T'; 41 s -= a[i].second; 42 } 43 } 44 for (int i = str.size() - 1; i >= 0; i--) 45 cout << str[i]; 46 } 47 else 48 cout << "No"; 49 return 0; 50 }
详细题解:https://atcoder.jp/contests/abc271/editorial/4939
标签:技巧,卡片,int,----,second,include,dp,first From: https://www.cnblogs.com/cilinmengye/p/16753607.html