完全背包问题。因为这里的竞赛题说的是可以在一类竞赛题当中选择多次,并且竞赛的题目以及所用的时间都是有限制的,所以会想到用完全背包的问题来解决。
首先上DFS:
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
#include<sstream>
#include<numeric>
#include<map>
#include<limits.h>
#include<set>
#define int long long
#define MAX 10005
#define _for(i,a,b) for(int i=a;i<(b);i++)
#define ALL(x) x.begin(),x.end()
using namespace std;
using PII=pair<int, int>;
int n, m;
int counts;
int t[MAX];
int w[MAX];
int f[MAX];
int dfs(int u, int sumF) {
if (u > m)
return 0;
if (sumF < t[u])
return dfs(u + 1, sumF);
else
return max(dfs(u + 1, sumF), dfs(u, sumF - t[u]) + w[u]);
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin >> n >> m;
for (int i = 1; i <= m; i++) {
cin >> w[i] >> t[i];
}
int res = dfs(1, n);
cout << res;
return 0;
}
然后是记忆化搜索:
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
#include<sstream>
#include<numeric>
#include<map>
#include<limits.h>
#include<set>
#define int long long
#define MAX 10005
#define _for(i,a,b) for(int i=a;i<(b);i++)
#define ALL(x) x.begin(),x.end()
using namespace std;
using PII=pair<int, int>;
int n, m;
int counts;
int t[MAX];
int w[MAX];
int f[MAX];
int mem[MAX][MAX];
int dfs(int u, int sumF) {
if (mem[u][sumF])
return mem[u][sumF];
if (u > m)
return 0;
int sum = 0;
if (sumF < t[u])
sum = dfs(u + 1, sumF);
else
sum = max(dfs(u + 1, sumF), dfs(u, sumF - t[u]) + w[u]);
mem[u][sumF] = sum;
return sum;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin >> n >> m;
for (int i = 1; i <= m; i++) {
cin >> w[i] >> t[i];
}
int res = dfs(1, n);
cout << res;
return 0;
}
最后就是优化的DP,这里注意到与01背包不一样的地方就是内层循环是正序遍历的,因为如果是倒着遍历的话,根据数组的递推我们会发现数组只会对于前面已经更新过的状态只用一次,而不会用多次,正序的话恰恰相反,它会把没有推出来的状态一次一次运用,也就是一步一步递推,把未知推到已知,01背包是已知推未知。
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
#include<sstream>
#include<numeric>
#include<map>
#include<limits.h>
#include<set>
#define int long long
#define MAX 10005
#define _for(i,a,b) for(int i=a;i<(b);i++)
#define ALL(x) x.begin(),x.end()
using namespace std;
using PII=pair<int, int>;
int n, m;
int counts;
int t[MAX];
int w[MAX];
int f[MAX];
int mem[MAX][MAX];
int dfs(int u, int sumF) {
if (mem[u][sumF])
return mem[u][sumF];
if (u > m)
return 0;
int sum = 0;
if (sumF < t[u])
sum = dfs(u + 1, sumF);
else
sum = max(dfs(u + 1, sumF), dfs(u, sumF - t[u]) + w[u]);
mem[u][sumF] = sum;
return sum;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin >> n >> m;
for (int i = 1; i <= m; i++) {
cin >> w[i] >> t[i];
}
for (int i = 1; i <= m; i++) {
for (int j = 0; j <= n; j++) {
if (j < t[i])
f[j] = f[j];
else
f[j] = max(f[j], f[j - t[i]] + w[i]);
}
}
cout << f[n];
return 0;
}