ACM学习汇总
P1060 开心的金明
有N元,m件商品,买第i件商品得到的值 t[i] = val[i]*wei[i]
求所买商品的t[i]总和最大值
-----------------------------------------------------------------------------
01背包裸题
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; i++)
using namespace std;
const int maxn = 30005;
int n,m,v[maxn],w[maxn],f[maxn];
void get_zero_one(){
fo(i,1,m){
for(int j=n; j>0; j--){
if(j-v[i]>=0)f[j] = max(f[j], f[j-v[i]]+v[i]*w[i]);
}
}
cout<<f[n];
}
int main(){
scanf("%d%d",&n,&m);
fo(i,1,m)scanf("%d%d",&v[i],&w[i]);
get_zero_one();
return 0;
}
P1164 小A点菜
N元,m件商品,每件价格为a[i],问刚好买完N元的方案数
-------------------------------------------------
f[0]=1,直接01背包
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; i++)
using namespace std;
int n,m,a[105];
int f[10005];
void zero_one_back(){
f[0] = 1;
fo(i,1,n){
for(int j=m; j>=a[i]; j--){
f[j] += f[j-a[i]];
}
}
cout<<f[m];
}
int main(){
scanf("%d%d",&n,&m);
fo(i,1,n)scanf("%d",&a[i]);
zero_one_back();
return 0;
}
P1064 金明的预算方案
N元,m件商品,求价格*权重和的最大值
商品有主从件之分,要先买了主件才能买从件
----------------------------------------
01背包,在枚举商品的时候判断是否为主件
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
struct node{
int v, p, q;
struct node *son1=NULL,*son2=NULL;
}a[70];
int n,m,f[40000];
void solve(){
fo(i,1,m){
if(a[i].q==0){
for(int j=n; j>=a[i].v; j--){
f[j] = max(f[j], f[j-a[i].v]+a[i].v*a[i].p);
if(a[i].son1!=NULL){
if(j-a[i].v-a[i].son1->v>=0)
f[j] = max(f[j], f[j-a[i].v-a[i].son1->v]+a[i].v*a[i].p+a[i].son1->v*a[i].son1->p);
}
if(a[i].son2!=NULL){
if(j-a[i].v-a[i].son2->v>=0)
f[j] = max(f[j], f[j-a[i].v-a[i].son2->v]+a[i].v*a[i].p+a[i].son2->v*a[i].son2->p);
}
if(a[i].son1!=NULL && a[i].son2!=NULL){
if(j-a[i].v-a[i].son1->v-a[i].son2->v>=0)
f[j] = max(f[j], f[j-a[i].v-a[i].son1->v-a[i].son2->v]+a[i].v*a[i].p+a[i].son1->v*a[i].son1->p+a[i].son2->v*a[i].son2->p);
}
}
}
}
cout<<f[n];
}
int main(){
cin>>n>>m;
fo(i,1,m){
scanf("%d%d%d",&a[i].v,&a[i].p,&a[i].q);
if(a[i].q){
if(a[a[i].q].son1==NULL)a[a[i].q].son1 = &a[i];
else a[a[i].q].son2 = &a[i];
}
}
solve();
return 0;
}
P1048 采药
时间N,m个草药,采药时间花费为w[i],价值为v[i],求采药总价值最大
------------------------------------------------------------
直接01背包
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
int f[1005],v[105],w[105],n,m;
void zero_one_pack(){
fo(i,1,m){
for(int j=n; j>=v[i]; j--){
f[j] = max(f[j], f[j-v[i]]+w[i]);
}
}
cout<<f[n];
}
int main(){
cin>>n>>m;
fo(i,1,m){
scanf("%d%d",&v[i],&w[i]);
}
zero_one_pack();
return 0;
}
P1049 装箱问题
箱子体积V,m件物品体积v[i],问怎么装才使得剩余体积最小,输出最小剩余体积
--------------------------------------------------------------------
f[n]表示n体积最多放的体积为f[n]
01背包后输出n-f[n]
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
int n,m,f[20005],v[40];
void solve(){
fo(i,1,m){
for(int j=n; j>=v[i]; --j){
f[j] = max(f[j], f[j-v[i]]+v[i]);
}
}
cout<<n-f[n];
}
int main(){
cin>>n>>m;
fo(i,1,m)scanf("%d",&v[i]);
solve();
return 0;
}
P1616 疯狂的采药
时间N,m种药,采药时间t[i],价值v[i],每株药无限,求最大采药价值
-----------------------------------------------------------
完全背包
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
int n,m,f[100005],v[10005],w[10005];
void solve(){
fo(i,1,m){
for(int j=v[i]; j<=n; j++){
f[j] = max(f[j], f[j-v[i]]+w[i]);
}
}
cout<<f[n];
}
int main(){
cin>>n>>m;
fo(i,1,m)scanf("%d%d",&v[i],&w[i]);
solve();
return 0;
}