背包DP模板

01背包模板

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define int long long
using namespace std;
const int N=1000;
int v[N+50],w[N+50];
int f[N+50];
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>v[i]>>w[i];
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=m;j>=v[i];j--)
		{
			f[j]=max(f[j],f[j-v[i]]+w[i]);
		}
	}
	cout<<f[m];
	return 0;
}

完全背包模板

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define int long long
using namespace std;
const int N=1000;
int v[N+50],w[N+50];
int f[N+50];
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>v[i]>>w[i]; 
	} 
	for(int i=1;i<=n;i++)
	{
		for(int j=v[i];j<=m;j++)
		{
			f[j]=max(f[j],f[j-v[i]]+w[i]);
		}
	}
	cout<<f[m];
	return 0;
}

多重背包模板 I

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define int long long
using namespace std;
const int N=1000;
int v[N+50],w[N+50],s[N+50];
int f[N+50];
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>v[i]>>w[i]>>s[i];
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=m;j>=v[i];j--)
		{
			for(int k=0;k<=s[i]&&k*v[i]<=j;k++)
			{
				f[j]=max(f[j],f[j-k*v[i]]+k*w[i]);
			}
		}
	}
	cout<<f[m];
	return 0;
}

多重背包模板 II

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define int long long
using namespace std;
const int N=100000;
int vv[N+50],ww[N+50];
int f[N+50];
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n,m;
	cin>>n>>m;
	int num=1;
	for(int i=1;i<=n;i++)
	{
		int v,w,s;
		cin>>v>>w>>s;
		for(int j=1;j<=s;j<<=1)
		{
			vv[num]=j*v;
			ww[num]=j*w;
			num++;
			s-=j;
		}
		if(s)
		{
			vv[num]=s*v;
			ww[num]=s*w;
			num++;
		}
	}
	for(int i=1;i<num;i++)
	{
		for(int j=m;j>=vv[i];j--)
		{
			f[j]=max(f[j],f[j-vv[i]]+ww[i]);
		} 
	}
	cout<<f[m];
	return 0;
}

多重背包模板 III

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define int long long
using namespace std;
const int N=20000;
int f[N+50],g[N+50],q[N+50];
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n,m;
	cin>>n>>m;
	int num=1;
	for(int i=1;i<=n;i++)
	{
		memcpy(g,f,sizeof(f));
		int v,w,s;
		cin>>v>>w>>s;
		for(int j=0;j<v;j++)
		{
			int h=0,t=-1;
			for(int k=j;k<=m;k+=v)
			{
				if(h<=t&&q[h]<k-s*v)
				{
					h++;
				}
				if(h<=t)
				{
					f[k]=max(g[k],g[q[h]]+(k-q[h])/v*w);
				}
				while(h<=t&&g[k]>=g[q[t]]+(k-q[t])/v*w)
				{
					t--;
				}
				q[++t]=k;
			}
		}
	}
	cout<<f[m];
	return 0;
}

混合背包模板

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define int long long
using namespace std;
const int N=1000;
int f[N+50],g[N+50],q[N+50];
int n,m;
void ZeroOnePack(int v,int w)
{
	for(int j=m;j>=v;j--)
	{
		f[j]=max(f[j],f[j-v]+w);
	}
}
void CompletePack(int v,int w)
{
	for(int j=v;j<=m;j++)
	{
		f[j]=max(f[j],f[j-v]+w);
	}
}
void MultiplePack(int v,int w,int s)
{
	memcpy(g,f,sizeof(f));      
  	for(int j=0;j<v;j++)
	{
    	int h=0,t=-1;
    	for(int k=j;k<=m;k+=v)
		{
      		if(h<=t&&q[h]<k-s*v)
			{
			 	h++;
			}
      		if(h<=t)
	  		{
	  			f[k]=max(g[k],g[q[h]]+(k-q[h])/v*w);
	  		}
      		while(h<=t&&g[k]>=g[q[t]]+(k-q[t])/v*w)
			{
			  	t--;
			}
      		q[++t]=k;
      	}
    }
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		int v,w,s;
		cin>>v>>w>>s;
		if(s==-1)
		{
			ZeroOnePack(v,w);
		}
		else if(s==0)
		{
			CompletePack(v,w);
		}
		else
		{
			MultiplePack(v,w,s);
		}
	}
	cout<<f[m];
	return 0;
}

二维费用的背包模板

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define int long long
using namespace std;
const int N=1000;
int f[N+50][N+50];
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n,V,M;
	cin>>n>>V>>M;
	for(int i=1;i<=n;i++)
	{
		int v,m,w;
		cin>>v>>m>>w;
		for(int j=V;j>=v;j--)
		{
			for(int k=M;k>=m;k--)
			{
				f[j][k]=max(f[j][k],f[j-v][k-m]+w);
			}
		}
	}
	cout<<f[V][M];
	return 0;
}

分组背包模板

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define int long long
using namespace std;
const int N=100;
int v[N+50],w[N+50];
int f[N+50];
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n,V;
	cin>>n>>V;
	for(int i=1;i<=n;i++)
	{
		int s;
		cin>>s;
		for(int j=1;j<=s;j++)
		{
			cin>>v[j]>>w[j];
		}
		for(int j=V;j>=1;j--)
		{
			for(int k=0;k<=s;k++)
			{
				if(j>=v[k])
				{
					f[j]=max(f[j],f[j-v[k]]+w[k]);
				}
			}
		}
	}
	cout<<f[V];
	return 0;
}

有依赖的背包模板

#include<iostream>
#include<cstring>
using namespace std;

const int N=110;
int n,V,p,root;
int v[N],w[N]; 
int h[N],to[N],ne[N],tot; //邻接表
int f[N][N];

void add(int a,int b){
  to[++tot]=b;ne[tot]=h[a];h[a]=tot;
}
void dfs(int u){
  for(int i=v[u];i<=V;i++) f[u][i]=w[u];
  for(int i=h[u]; i; i=ne[i]){  //子节点 
    int s=to[i];
    dfs(s);
    for(int j=V;j>=v[u];j--)    //体积
      for(int k=0;k<=j-v[u];k++)//决策
        f[u][j]=max(f[u][j],f[u][j-k]+f[s][k]);
  }
}
int main(){
  cin>>n>>V;              //物品个数,背包容量
  for(int i=1;i<=n;i++){
    cin>>v[i]>>w[i]>>p;   //体积,价值,依赖的物品编号
    if(p==-1) root=i;
    else add(p,i);
  }
  dfs(root);
  cout<<f[root][V];
}

背包问题求方案数模板

// 不超背包容量的方案数
#include<iostream>
#include<cstring>
using namespace std;

const int N=1010, mod=1e9+7;
int f[N],c[N];
// f[i]表示背包容量为i时最优选法的总价值
// c[i]表示背包容量为i时最优选法的方案数

int main(){
  int n, m, v, w;   
  scanf("%d%d", &n, &m);    
  for(int i=0;i<=m;i++) c[i]=1;    
  
  for(int i=1; i<=n; i++){    //枚举物品
    scanf("%d%d",&v,&w);
    for(int j=m; j>=v; j--){  //枚举体积
      if(f[j-v]+w>f[j]){      //装新物品总价值更大
        f[j]=f[j-v]+w;
        c[j]=c[j-v];
      }
      else if(f[j-v]+w==f[j]) //装新物品总价值相等
        c[j]=(c[j]+c[j-v])%mod;     
    }
  }
  printf("%d\n",c[m]);
}

背包问题求具体方案模板

#include<iostream>
#include<cstring>
using namespace std;

const int N = 1010;
int v[N],w[N];
int f[N][N],p[N][N];

int main(){
  int n,m; cin>>n>>m;
  for(int i=1; i<=n; i++) cin>>v[i]>>w[i];
  
  for(int i=n; i>=1; i--)   //逆序取物 
  for(int j=0; j<=m; j++){  //枚举体积
    f[i][j]=f[i+1][j];
    p[i][j]=j;              //记录路径列 
    if(j>=v[i])
      f[i][j]=max(f[i][j],f[i+1][j-v[i]]+w[i]);
    if(j>=v[i] && f[i][j]==f[i+1][j-v[i]]+w[i])
      p[i][j]=j-v[i];
  }
  
  int j=m;
  for(int i=1; i<=n; i++)
    if(p[i][j]<j){
      printf("%d ",i);
      j=p[i][j];
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值