C题
一个二维背包问题
//二维背包 #include <bits/stdc++.h> using namespace std; const int MAXN = 1010; int t[MAXN], a[MAXN], w[MAXN]; int dp[MAXN][MAXN]; int main () { ios::sync_with_stdio(false); cin.tie(0); int c; cin >> c; while(c--) { int tt, aa; cin >> tt >> aa; int n; cin >> n; for(int i = 1; i <= n; ++i) { cin >> t[i] >> a[i] >> w[i]; } memset(dp, 0x3f3f3f3f, sizeof dp); dp[0][0]= 0; for(int i = 1; i <= n; ++i) { for(int j = tt; j >= 0; --j) { for(int k = aa; k >= 0; --k) { int x = j + t[i] > tt ? tt: j + t[i]; int y = k + a[i] > aa ? aa : k + a[i]; dp[x][y] = min(dp[x][y], dp[j][k] + w[i]); // cout << dp[x][y] << endl; } } } cout << dp[tt][aa] << endl; } } /* 1 5 60 5 3 36 120 10 25 129 5 50 250 1 45 130 4 20 119 */
D题
与昨天的DP题类似
#include <bits/stdc++.h> using namespace std; int a[110][110]; int dp[110][110]; int main () { ios::sync_with_stdio(false); cin.tie(0); int T; cin >> T; while(T--) { memset(a, 0, sizeof a); memset(dp, 0, sizeof dp); int h, w; cin >> h >> w; for(int i = 1; i <= h; ++i) { for(int j = 1; j <= w; ++j) { cin >> a[i][j]; if(i == 1) { dp[i][j] = a[i][j]; } } } for(int i = 2; i <= h; ++i) { for(int j = 1; j <= w; ++j) { dp[i][j] = max(max(dp[i - 1][j - 1], dp[i - 1][j]), dp[i - 1][j + 1]) + a[i][j]; } } int ans = -1; for(int i = 1; i <= w; ++i) { ans = max(ans, dp[h][i]); } cout << ans << endl; } }
E题
跟上面的题类似
#include <bits/stdc++.h> using namespace std; int a[110][110]; int dp[110][110]; int main () { ios::sync_with_stdio(false); cin.tie(0); // int T; // cin >> T; // while(T--) { memset(a, 0, sizeof a); memset(dp, 0x3f3f3f3f, sizeof dp); int h, w; cin >> h >> w; for(int i = 1; i <= h; ++i) { for(int j = 1; j <= w; ++j) { cin >> a[i][j]; if(i == 1) { dp[i][j] = a[i][j]; } } } for(int i = 2; i <= h; ++i) { for(int j = 1; j <= w; ++j) { dp[i][j] = min(min(dp[i - 1][j - 1], dp[i - 1][j]), dp[i - 1][j + 1]) + a[i][j]; } } int ans = 0x3f3f3f3f; for(int i = 1; i <= w; ++i) { ans = min(ans, dp[h][i]); } cout << ans << endl; // } }
F题
典型的背包问题需要注意的是j从30开始取别从sum开始取,不然会被T
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int main() { int t; scanf("%d",&t); while(t--) { int p[1100],w[1100],n; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d%d",&p[i],&w[i]); int dp[50]; memset(dp,0,sizeof(dp)); for(int i=0;i<n;i++) for(int j=30;j>=w[i];j--) if(dp[j]<dp[j-w[i]]+p[i]) dp[j]=dp[j-w[i]]+p[i]; int G,sum=0; scanf("%d",&G); while(G--) { int MW; scanf("%d",&MW); sum+=dp[MW]; } printf("%d ",sum); } return 0; }
G题
easy,一维DP题
#include <bits/stdc++.h> using namespace std; typedef long long ll; ll a[10010]; ll dp[10010]; int main (){ ios::sync_with_stdio(false); cin.tie(0); int T; cin >> T; int num = 1; while(T--) { memset(dp, 0, sizeof dp); memset(a, 0, sizeof a); int N; cin >> N; for(int i = 1; i <= N; ++i) { cin >> a[i]; } dp[1] = a[1]; for(int i = 2; i <= N; ++i) { dp[i] = max(dp[i - 1], dp[i - 2] + a[i]); } cout << "Case " << num++ << ": "; cout << dp[N] << endl; } }
H题
比较有灵性的DP题(背包问题)
不过首先需要将素数打表,然后由背包问题求解
//变形的背包问题 #include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN = 5000; int pri[MAXN], vis[MAXN]; int cnt = 0; int n = 1250; int dp[1300][20]; void Pri() { for(int i = 2; i <= n; ++i) { if(!vis[i]) { pri[++cnt] = i; } for(int j = 1; j <= cnt && i * pri[j] <= n; ++j) { vis[i * pri[j]] = 1; if(i % pri[j] == 0) { break; } } } } void solve() { dp[0][0] = 1; for(int i = 1; i <= cnt; ++i) { for(int j = n; j >= pri[i]; --j) { for(int k = 1; k <= 15; ++k) { dp[j][k] += dp[j - pri[i]][k - 1]; } } } } int main (){ ios::sync_with_stdio(false); cin.tie(0); Pri(); solve(); ll n, k; while(cin >> n >> k && (n + k)){ cout << dp[n][k] << endl; } }