背包问题可以去看一下背包九讲
0-1背包
https://www.luogu.org/problemnew/show/P1048
记忆化搜索代码:
/**
* memory search
* P1048
* @author Hongchuan CAO
*/
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<cstdio>
using namespace std;
int val[110][2];
int mem[110][1010];
int t,m;
int result = 0;
void clear(){
for(int i=0;i<110;i++){
for(int j=0;j<1010;j++){
mem[i][j] = -1;
}
}
}
void get_data(){
scanf("%d%d",&t,&m);
for(int i=0;i<m;i++){
scanf("%d%d",&val[i][0],&val[i][1]);
}
}
int dfs(int index,int lleft){
//if searched, return directly
if(mem[index][lleft]!=-1) return mem[index][lleft];
//return 0 if index>=m
if(index>=m) return 0;
int chose=0,uchose=0;
//divide into two condition (choose or not)
uchose = dfs(index+1,lleft);
if(lleft>=val[index][0]){
chose = dfs(index+1,lleft-val[index][0])+val[index][1];
}
//add to memory array
return mem[index][lleft] = max(uchose,chose);
}
int main(){
clear();
get_data();
printf("%d\n",dfs(0,t));
return 0;
}
DP代码:
状态转移方程:
由于状态
都是由状态
转化来的,所以可以将二维数组压缩为一维数组。
这个代码的状态
为在第
个草药花费时间为
时的最大价值(此时的时间花费或许并不等于j,应该是小于等于j)
所以在初始化的时候所有的值都为0
/**
* DP : dp[j] = max(dp[j],dp[j-w[i]]+val[i]);
* p1048
* @author Hongchuan CAO
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
using namespace std;
const int INF = 1e8;
int t,m;
int dp[1010];
int stat[110][2];
//all inital is zero which is important
void get_data(){
scanf("%d%d",&t,&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&stat[i][0],&stat[i][1]);
}
}
void solve(){
for(int i=1;i<=m;i++){
for(int j=t;j>=stat[i][0];j--){
dp[j] = max(dp[j],dp[j-stat[i][0]]+stat[i][1]);
}
}
printf("%d\n",dp[t]);
}
int main(){
get_data();
solve();
return 0;
}
还有一种做法为
状态
为在第
个草药花费时间恰好为
时的最大价值
在初始化的时候只有dp[0][0]为0,其他的值都是负无穷 其实这个地方的负无穷是为了使那些不能恰好的点一直为负数,也可以进行特判,遇到这样的点可以直接跳过状态转移方程。
所以到最后,最终的结果并不是
,而是
中的最大值。(因为其中所有的结果都是恰好填满时间的最大价值)
/**
* DP : dp[j] = max(dp[j],dp[j-w[i]]+val[i]);
* p1048
* @author Hongchuan CAO
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
using namespace std;
const int INF = 1e8;
int t,m;
int dp[1010];
int stat[110][2];
void clear(){
for(int i=1;i<1010;i++) dp[i] = -INF;
dp[0] = 0;
}
void get_data(){
scanf("%d%d",&t,&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&stat[i][0],&stat[i][1]);
}
}
void solve(){
int maxx = -1;
for(int i=1;i<=m;i++){
for(int j=t;j>=stat[i][0];j--){
dp[j] = max(dp[j],dp[j-stat[i][0]]+stat[i][1]);
}
}
for(int i=0;i<=t;i++){
maxx = max(maxx,dp[i]);
}
printf("%d\n",maxx);
}
int main(){
clear();
get_data();
solve();
return 0;
}
完全背包
https://www.luogu.org/problemnew/show/P1616