C题
一个二维背包问题
//二维背包
#include
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
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
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
#include
#include
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
scanf("%d%d",&p[i],&w[i]);
int dp[50];
memset(dp,0,sizeof(dp));
for(int i=0;i
for(int j=30;j>=w[i];j--)
if(dp[j]
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
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
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;
}
}