动态规划dp

P1057
就是要找到两子状态,然后定好开头状态
求可能是从左边,可能是右边

#include<iostream>
using namespace std;
int f[31][31]={1};
int main()
{
	int m,n;//m是次数,n 是人数 
	cin>>n>>m;
	
	for(int i=1;i<=m;i++)
	{
		for(int j=0;j<n;j++)
		{
			f[i][j]=f[i-1][(j+1)%n]+f[i-1][(j-1+n)%n];
		}
	}
	cout<<f[m][0];
}

有一个很妙的就是解决越界问题的,取余了吧

P1216
一个逐步递推就好了,可以用一个滚动数组来节省空间
选一个最大的加上自身

#include<iostream>
#include<math.h>
using namespace std;
int a[1001][1001] ;
int main()
{
	int m;
	cin>>m;
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=i;j++)
		{
			cin>>a[i][j];
		}
	}
	for(int i=m-1;i>=1;i--)
	{
		for(int j=1;j<=i;j++)
		{
			a[i][j]=max(a[i+1][j],a[i+1][j+1])+a[i][j];
		}
	}
	cout<<a[1][1];
}

逃不掉的背包问题
01背包,目的是最大价值,两重循环,第一重循环是背包里面物品的个数,第二重是背包体积开始向前
然后判断加还是不加,加的话要减去体积,然后加上价值

#include<iostream>
#include<cmath>
using namespace std;
int dp[10001];
int main()
{
	int T,M,t,m;
	cin>>T>>M;
	for(int i=1;i<=M;i++)
	{
		cin>>t>>m;
		for(int j=T;j>=t;j--)
		{
			dp[j]=max(dp[j],dp[j-t]+m) ;
		}
		
	}
	cout<<dp[T];
	return 0;
}

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
这里的价值和个数都是体积

#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];
	
}

P1802
就是说要分个类,不同条件下有不同的值
,设置结构体调用的时候要想小心一点

#include<iostream>
using namespace std;
long long int f[10086];
struct node
{
	int lose;
	int win;
	int ge;
}aa[10086];
int main()
{
	int n,x;
	cin>>n>>x;
	for(int i=1;i<=n;i++)
	{
		int a,b,c; 
		cin>>a>>b>>c;
		aa[i].lose =a;
		aa[i].win =b;
		aa[i].ge =c;
	}
	for(int i=1;i<=n;i++)
	{
	  for(int j=x;j>=0;j--)
	  {
	  	if(j>=aa[i].ge )
	  	{
	  	  f[j]=max(f[j]+aa[i].lose ,f[j-aa[i].ge ]+aa[i].win );
		  }
		  else
		  {
		  	f[j]=f[j]+aa[i].lose ;
		  }
	  }
	}
	cout<<f[x]*5;
	
}

P1734
背包总体积就是数的大小,个数就是小于它的这些数字,然后价值就是自己打个表循环赋值

//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;
}

P1050
本意是要求最少用的精力,把石头都搬走,就是说把石当作背包的总体积,但是就是说精力要最小,有点难理解
可以把精力当作总的价值,毕竟这个不需要变成001,然后石头就是物品,然后再去查正好搬到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;
这种就要分成两份,然后总的物件是数字,总价值是他们的和,然后每一次都是选自己和不选自己;

//背包能装物品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;
	
 } 

P1616
是个完全背包,就是要从头往后第二轮循环

#include<bits/stdc++.h>

using namespace std;
long long int dp[100010];
int N,M,a,b;
int main()
{
     
	cin>>N>>M;
	for(int i=1;i<=M;i++)
	{
		cin>>a>>b;
		for(int j=a;j<=N;j++)
		{
			dp[j]=max(dp[j],dp[j-a]+b); 
		}
	 } 
	 cout<<dp[N];
	 return 0;
 } 

P1679
求最小的,就是每一次min,然后所以一开始要赋值最大,然后记得第一个是0,至于有几个物品就自己循环出来

#include<iostream>
#include<cstring>
using namespace std;
int dp[100010],a[123];
int main()
{
	long int m,n;
	cin>>m;

	memset(dp,61,sizeof(dp));
	dp[0]=0;
	dp[1]=1;
	for(int i=1;i<=m;i++)
	{
		a[i]=i*i*i*i;
		if(a[i]>=m)
		{
			n=i;
			break;
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=a[i];j<=m;j++)
		dp[j]=min(dp[j],dp[j-a[i]]+1);
	}
	cout<<dp[m];
}

P1757
分组背包,就是每一次每一组要选出来最好的然后去参与,每一次都i要比,每一次都出来最好的
bag的结构体,要放入一个组数

#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
放一个40分的我觉得完美的精明预算方案
就是说要分成四个组,每一个包里面有四个组,四个组就是用数组来表示

在这里插入代码#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;
 } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值