zoukankan      html  css  js  c++  java
  • 背包规划集合

    越来越菜了,现在连个暴力都打不出来了

    背包

    P1048采药

    01背包板子

    [f[i][j] = max egin{cases} f[i-1][j] \ f[i-1][j-V_{k}]+W_{k} end{cases} ]

    
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    
    using namespace std;
    
    #define int long long 
    
    const int p=1e5+6;
    
    template<typename _T>
    void read(_T &x)
    {
    	x=0;char s=getchar();int f=1;
    	while(s<'0'||s>'9'){f=1;if(s=='-')f=-1;s=getchar();}
    	while('0'<=s&&s<='9'){x=(x<<1)+(x<<3)+s-'0';s=getchar();}
    	x*=f;
    }
    
    int f[2333][2333];
    int v[2333],w[2333];
    
    signed main()
    {
    	int T,M;
    
    	read(T);
    	read(M);
    	
    	for(int i=1;i<=M;i++)
    	{
    		read(w[i]);
    		read(v[i]);
    	}
    	
    	for(int i=1;i<=M;i++)
    		for(int j=1;j<=T;j++)
    	{
    		if(j-w[i] >=0)
    		f[i][j] = max(f[i-1][j] , f[i-1][j-w[i]]+v[i]);
    		else f[i][j] = f[i-1][j];
    	}
    	
    	cout<<f[M][T];
    }
    
    

    P1757分组背包

    [f[i][j] = max egin{cases} f[i-1][j]\ max_{1≤k≤C_i}f[i-1][j-V_{ik}]+W_{ik} end{cases} ]

    有一点需要注意,分组背包的阶段是组数
    状态是体积
    决策是组中物品
    所以体积要放在物品之外

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<queue>
    
    using namespace std;
    
    template<typename _T>
    inline void read(_T &x)
    {
    	x=0;char s=getchar();int f=1;
    	while(s<'0'||s>'9'){f=1;if(s =='-')f=-1;s=getchar();}
    	while('0'<=s&&s<='9'){x=(x<<1)+(x<<3)+s-'0';s=getchar();}
    	x*=f;
    }
    
    int w[2333],v[2333];
    vector<int>c[2333];
    int f[2223][2333];
    
    signed main()
    {
    	int n,m;
    	
    	read(m);
    	read(n);
    	
    	int maxn = 1;
    	
    	for(int i=1,a,b,g;i<=n;i++)
    	{
    		read(v[i]);
    		read(w[i]);
    		read(g);
    		c[g].push_back(i);
    		maxn = max(g,maxn);
    	}
    	
    	memset(f,0xcf,sizeof(f));
    	
    	for(int j=0;j<=m;j++) f[0][j]=0;
    
    	for(int i=1;i<=maxn;i++)
    		for(int j=0;j<=m;j++)
    		{
    			
    			f[i&1][j] =f[(i-1)&1][j];
    			
    			for(int k=0,id;k!=c[i].size();k++)
    			{
    				id = c[i][k];
    				if(j>=v[id])
    				f[i&1][j] = max(f[i&1][j] , f[(i-1)&1][j-v[id]]+w[id]);
    			}
    		}
    		
    	cout<<f[maxn&1][m];
    }
    

    P1616完全背包

    [f[i][j] = max egin{cases} f[i-1][j]\ f[i][j-V_{i}]+W_{i} end{cases} ]

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    
    using namespace std;
    
    const int p=1e5+5;
    #define int long long 
    
    template<typename _T>
    void read(_T &x)
    {
    	x =0;char s=getchar();int f=1;
    	while(s<'0'||s>'9'){f=1;if(f=='-')f=-1;s=getchar();}
    	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+s-'0';s=getchar();}
    	x*=f;
    }
    
    int v[p],w[p];
    int f[233333333];
    
    signed main()
    {
    	int t,m;
    	
    	ios_base::sync_with_stdio(false);
    	cout.tie(NULL);
    	cin.tie(NULL);
    	
    	read(t);read(m);
    	
    	for(int i=1;i<=m;i++)
    	{
    		read(w[i]);
    		read(v[i]);
    	}
    	
    	for(int i=1;i<=m;i++)
    		for(int j=1;j<=t;j++)
    	{
    		if(j-w[i] >= 0)
    		f[j] = max(f[j],f[j-w[i]]+v[i]);
    	}
    	
    	cout<<f[t];
    
    }
    

    P1776多重背包

    暴力复杂度(O(M*sum_{i=1}^{N}C_i))

    所以采用二进制拆分法
    主要思想:
    把数量为Ci的第i种物品拆成p+2个物品,他们的体积分别为

    [2^0*V_i,2^1*V_i cdots ,2^p*V_i,R_i*V_i ]

    这p+2个物品可以凑成0~Ci任意物品数目组合
    复杂度(O(M*sum_{i=1}^NlogC_i))

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    
    using namespace std;
    
    #define int long long 
    
    const int p=5e5+5;
    
    template<typename _T>
    void read(_T &x)
    {
    	x=0;char s=getchar();int f=1;
    	while('0'>s||s>'9'){f=1;if(s=='-')f=-1;s=getchar();}
    	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+s-'0';s=getchar();}
    	x*=f;
    }
    
    int v[p];
    int w[p];
    int tit = 0;
    int f[3][p];
    
    signed main()
    {
    	ios_base::sync_with_stdio(false);
    	cout.tie(NULL);
    	cin.tie(NULL);
    	
    	int n,m;
    	
    	read(n);
    	read(m);
    	
    	for(int i=1,a,b,c;i<=n;i++)	
    	{
    		read(a);
    		read(b);
    		read(c);
    		
    		for(int j=1;j<=c;j<<=1)
    		{
    			v[++tit] = j*a;
    			w[tit] = j* b;
    			c-=j;
    		}
    		if(c)
    		{
    			v[++tit] = c*a,w[tit] = c*b;
    		 } 
    	}
    
    	for(int i=1;i<=tit;i++)
    	{
    		memset(f[i&1],0,sizeof(f[i&1]));
    		
    		for(int j=1;j<=m;j++)
    		{
    			if(j-w[i] >=0)
    			f[i&1][j] = max(f[i-1&1][j] , f[i-1&1][j-w[i]]+v[i]);
    			else f[i&1][j] = f[i-1&1][j];
    		}
    		
    	}
    		
    	cout<<f[tit&1][m];
    	
    }
    

    (O(NM))的单调队列法我并不会,如果有一天我还在这里,再补上吧

    树形背包

    (f[now][j][k])为在以(now)为根的子树中,选前(j)个子节点,修(k)门课的最大收益

    [f[now][j][k] = max egin{cases} f[now][j-1][k]\ f[now][j-1][k-l]+f[son(j)][num(son(j))][l] end{cases} +score[now] ]

    显然我们可以把(j)的那一维压掉
    可以发现(k)是必然的大于(k-l)的,所以对于(k)我们需要倒序循环

    #include<iostream>
    #include<cstdio>
    
    using namespace std;
    
    int head[2333];
    int next[2333],ver[2333];
    int f[2333][233];
    int tot;
    int n,m;
    
    inline void add(int x,int y)
    {
    	ver[++tot]=y;
    	next[tot]=head[x];
    	head[x]=tot;
    }
    
    inline void dtgh(int now)
    {
    	for(int i=head[now];i;i=next[i])
    	{
    		dtgh(ver[i]);
    		
    		for(int j=m+1;j>1;j--)
    			for(int k=0;k<j;k++)
    			f[now][j]=max(f[now][j],f[now][j-k]+f[ver[i]][k]);
    	}
    }
    
    int main()
    {
    	ios_base::sync_with_stdio(false);
    	cout.tie(NULL);
    	cin.tie(NULL);
    	
    	cin>>n>>m;
    	
    	for(int i=1,k,s;i<=n;i++)
    	{
    		cin>>k>>s;
    		f[i][1]=s;//因为选择这个点就必定花费1,所以直接处理1的情况
    		add(k,i);
    	}
    	
    	dtgh(0);
    	
    	cout<<f[0][m+1];
     } 
    

    (End)

  • 相关阅读:
    SqlServer与Access之间的数据互导
    [转]半角<=>全角互转函数[JS版 VBS版]
    [文摘20070914]一个成功的博客必须知道的80个博客工具
    在javascript中获得由Ajax返回DataTable的列数和列名
    [转]获取xml节点值和属性值(兼容ie和firefox)
    [文摘20070920]网络战
    游标简单使用
    sql函数 得到 由 年月日时分秒+三位内的随机数 组成的随机数
    [转]ASP.NET 2.0 AJAX中Webservice调用方法示例 (包含参数类型为DataTable的WS方法)
    向页面中添加音乐或flash
  • 原文地址:https://www.cnblogs.com/-Iris-/p/14070708.html
Copyright © 2011-2022 走看看