首页 > 技术文章 > DP_包括一些背包问题

lightac 2020-10-07 19:39 原文

比赛链接

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\n",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;
	}
}

 

推荐阅读