概述部分
最短路问题
//最短路
#include<bits/stdc++.h>
using namespace std;
int n, m;
int a[1001][1001], dp[1001];
int main(){
cin >> n >> m;
memset(a, 127, sizeof(a));
for (int i = 1; i <= m; i++){
int x, y, z;
cin >> x >> y >> z;
a[x][y] = min(a[x][y], z);
}
memset(dp, 127, sizeof(dp));
dp[1] = 0;
for (int i = 2; i <= n; i++){
for (int j = 1; j < i; j++){
if (dp[j] < 1 << 30 && a[j][i] < 1 << 30){
dp[i] = min(dp[i], dp[j] + a[j][i]);
}
}
}
printf("%d\n", dp[n]);
return 0;
}
最长上升子序列
//最长上升子序列
#include<bits/stdc++.h>
using namespace std;
int n;
int a[1010];
int dp[1010];
int main(){
cin >> n;
for (int i = 1; i <= n; i++){
cin >> a[i];
}
dp[1] = 1;
int ans = 0;
for (int i = 2; i <= n; i++){
dp[i] = 1;
for (int j = 1; j < i; j++){
if (a[i] > a[j]){
dp[i] = max(dp[i], dp[j] + 1);
ans = max(ans, dp[i]);
}
}
}
printf("%d\n", ans);
return 0;
}
最长公共子序列
//最长公共子序列
#include<bits/stdc++.h>
using namespace std;
int n, m;
int a[1010], b[1010];
int dp[1010][1010];
int main(){
cin >> n >> m;
for (int i = 1; i <= n; i++){
cin >> a[i];
}
for (int i = 1; i <= m; i++){
cin >> b[i];
}
for (int i = 1; i <= n; i++){
for (int j = 1; j <= m; j++){
if (a[i] == b[j]){
dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + 1);
}
else {
dp[i][j] = max(max(dp[i][j], dp[i][j - 1]), dp[i - 1][j]);
}
}
}
printf("%d\n", dp[n][m]);
return 0;
}
背包问题
多重背包1
//多重背包1
#include<bits/stdc++.h>
using namespace std;
int n, m;
int v[1010], w[1010], l[1010];
int dp[1010];
int main(){
cin >> n >> m;
for (int i = 1; i <= n; i++){
cin >> v[i] >> w[i] >> l[i];
}
for (int i = 1; i <= n; i++){
for (int k = 1; k <= l[i]; k++){
for (int j = m; j >= v[i]; j--){
dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
}
}
}
printf("%d\n", dp[m]);
return 0;
}
分组背包
//分组背包
#include<bits/stdc++.h>
using namespace std;
int n, m;
int v[1010], w[1010], a[1010];
vector<int> c[1010];
int dp[1010][1010];
int main(){
cin >> n >> m;
for (int i = 1; i <= n; i++){
cin >> a[i] >> v[i] >> w[i];
c[a[i]].push_back(i);
}
for (int i = 1; i <= 1000; i++){
for (int j = 0; j <= m; j++){
dp[i][j] = dp[i - 1][j];
for (int k : c[i]){
if (v[k] <= j){
dp[i][j] = max(dp[i][j], dp[i - 1][j - v[k]] + w[k]);
}
}
}
}
printf("%d\n", dp[1000][m]);
return 0;
}
三维背包
//三维背包-解2
#include<bits/stdc++.h>
using namespace std;
int n, m, k;
int v[1010], w[1010], t[1010];
int dp[101][101];
int main(){
cin >> n >> m >> k;
for (int i = 1; i <= n; i++){
cin >> v[i] >> w[i] >> t[i];
}
for (int i = 1; i <= n; i++){
for (int j = m; j >= v[i]; j--){
for (int x = k; x >= t[i]; x--){
dp[j][x] = max(dp[j][x], dp[j - v[i]][x - t[i]] + w[i]);
}
}
}
printf("%d\n", dp[m][k]);
return 0;
}
总结:
背包问题是动态规划最经典的一类,要满足两个条件,最优子结构和无后效性,尤其是状态转移方程的正确性