顺序题单之外的DP (我爱DP)

P1060
这个东西的价值是重要度*价格,然后物品种类放外层

#include<iostream>
#include<math.h> 
using namespace std;
int dp[10000000];
int main()
{
	
	int N,M,a,b,c;
	cin>>N>>M;
	for(int i=1;i<=M;i++)
	{
		cin>>a>>b;
		c=a*b;
		for(int j=N;j>=a;j--)这里是a,包的承载量和价钱有关
		dp[j]=max(dp[j],dp[j-a]+c);
		
	}
	cout<<dp[N];
	return 0; 
}

P1049
有一点点绕,因为这个背包的物品和价值都是它的容积,然后就是只要有一维,一维里面减去的和外面加上的价值都是a

在#include<iostream>//价值和体积等价 
#include<math.h> 
using namespace std;
int dp[476587698];
int main()
{
	int V,n,a;
	cin>>V>>n;
	for(int i=1;i<=n;i++)
	{cin>>a;
		for(int j=V;j>=a;j--)
		{
			dp[j]=max(dp[j],dp[j-a]+a);
		}
	}
	cout<<V-dp[V];
	
}

当然还是把总的n放在外面的,但后面其实用不上

P1734
选取和不超过s,那么就用循环,循环里面判断约数,可以选择的数不超过s就可以,
a[i]里面存每一个物品的价值
然后约数采用背包思想

//s是背包的容量,价值是和 
#include<iostream>
int a[145435676],dp[2135564];
using namespace std;
int main()
{
	int S;
	cin>>S;
	
	for(int i=1;i<S;i++)
	{
		for(int j=1;j<i;j++)
		{if(i%j==0)
		a[i]+=j;
		}
	}
	for(int i=1;i<=S;i++)
	for(int j=S;j>=i;j--)
	{
		dp[j]=max(dp[j],dp[j-i]+a[i]);
	
	}
	cout<<dp[S];
	return 0;
}

P1510
转化一下,把精力作为价值,然后木石作为物品,然后求出来,需要最少精力,如果满足的话就ok

#include<iostream>
#include<string.h> 
using namespace std;
int dp[19977],vv,tl,flag;
int main()
{
    

	int v,n,c;
	cin>>v>>n>>c;
	for(int i=1;i<=n;i++)///多少块是物品可能性 
	{
		cin>>vv>>tl;
		for(int j=c;j>=tl;j--)//这个是体力,也就是背包的价值 
		{
			dp[j]=max(dp[j],dp[j-tl]+vv);//每次都是最少的 ,所以一开始要设置大 
		}
	}
	for(int i=1;i<=c;i++)
	{
		if(dp[i]>=v)
		{cout<<c-i;
		flag=1;
		break;
		}
		
		
	}
	if(flag==0)
	cout<<"Impossible";
 } 

P1466
对于这种题目其实也是背包,先求出来价值(也就是各个数字的和)然后物品个数就是一半,然后每一次都是+1
这种初始化得是1哦

//背包能装物品n/2,装物品价值就是他们和
#include<iostream>
using namespace std;
long long int dp[1002]={1};/long long 吞了一个点
int main()
{
	int n,m;
	cin>>n;
    
	m=(n+1)*n/2;//求和
	if(m%2==1)
    {
    	cout<<0;
    	return 0;
	}
	for(int i=1;i<=n;i++)//物品
	{
		for(int j=m/2;j>=i;j--)//价值
		{
			dp[j]+=dp[j-i];//加这个物品前的结合自己的
		}
	}
	cout<<dp[m/2]/2;
	return 0;
	
 } 

P1757
分组背包,对于每一次更新其实只能让这个组里面最好的去更新
可以用bag来存储,里面放上物品的体积和价值,还可以放一个w,来统计这个包里到底有多少东西
dp循环里面,最外层是包的数量,然后第二层是它的容积,然后第三层是循环这个i背包里面每个东西放进去,取最大值

#include<bits/stdc++.h>
using namespace std;
struct Bag
{
	int a[1010];
	int b[1010];
	int w;
}c[1001];
int dp[1010];
int main()
{
	int M,N,p=0;
	cin>>M>>N;
	for(int i=1;i<=N;i++)
	{
		int x,y,z; 
		cin>>x>>y>>z;
		p=max(p,z);
		c[z].w++;
		c[z].a[c[z].w]=x;
		c[z].b[c[z].w]=y;
		
	}
	for(int i=1;i<=p;i++)
	{
		for(int j=M;j>=0;j--)
		{
			for(int k=1;k<=c[i].w;k++)
			{
				if(j-c[i].a[k]>=0)
				dp[j]=max(dp[j],dp[j-c[i].a[k]]+c[i].b[k]);
			}
		}
	}
	cout<<dp[M];
	return 0;
}

P1064
每个主件可以有0,1,2个附件,所以就是说对于每个主件就是一个背包,这个背包里面有4种可能性,要把这个存进去

#include<iostream>
using namespace std;
int dp[12345]={0};
struct node
{
	int a[10202];
	int b[10202];
	int w;
}c[10202];
int main()
{
	int m,n,p;
	cin>>m>>n;
	for(int i=1;i<=n;i++)
	{
		int x,y,z; 
		cin>>x>>y>>z;
		
		if(z==0)
		{
		  c[i].w=1;
		  c[i].a[1]=x;
		  c[i].b[1]=y*x;
		}
		else
		{
			if(c[z].w ==1)
			{
				c[z].w =2;
				c[z].a[2] =x+c[z].a[1];
				c[z].b[2] =x*y+c[z].b[1];
			}
			else
			{
				c[z].a[3]=c[z].a[1]+x;
				c[z].b[3]=c[z].b[1]+x*y;
				c[z].a[4]=c[z].a [2]+x;
				c[z].b [4]=c[z].a [2]+x*y;	
				c[z].w=4;		}
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=m;j>=0;j--)
		{
			for(int k=1;k<=c[i].w ;k++)
			{
				if(j>=c[i].a[k])
			dp[j]=max(dp[j],dp[j-c[i].a[k]]+c[i].b[k])	;
			}
		 } 
	}
	cout<<dp[m];
	return 0;
 } 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值