决策型DP

比如经典的背包问题,每件物品有着选与不选两个决策,选的话就会导致状态的变化(更新)。

题目一:

https://www.luogu.org/problemnew/show/P1064

考虑主件,则每个主件有四种决策:不选,选一个主件,选一个主件加一个附件,选一个主件加两个附件,考虑每种决策可能对状态的更新就行了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<bitset>
#include<vector>
using namespace std;
typedef long long ll;
typedef struct NODE{
	int w,v;	
}node;
vector<node>vt[65];
int dp[32005]={0};
int a[100];
int main()
{	int n,m;
	cin>>n>>m;
	int tot=0;
	for(int i=1;i<=m;i++)
	{
		int w,v,x;
		cin>>w>>v>>x;
		if(x==0)
		{
			a[tot++]=i;
			vt[x].push_back((node){w,v});
		}
		else vt[x].push_back((node){w,v});
	}
	for(int i=0;i<tot;i++)
	{
		for(int j=n;j>=0;j--)
		{
			if(j>=vt[0][i].w)
			{
				dp[j]=max(dp[j],dp[j-vt[0][i].w]+vt[0][i].w*vt[0][i].v);
			}
			int l=vt[a[i]].size();
			if(l==2&&j>=vt[0][i].w+vt[a[i]][0].w+vt[a[i]][1].w)
			{
				int t=dp[j-(vt[0][i].w+vt[a[i]][0].w+vt[a[i]][1].w)];
				t+=vt[0][i].w*vt[0][i].v+vt[a[i]][0].w*vt[a[i]][0].v+vt[a[i]][1].w*vt[a[i]][1].v;
				dp[j]=max(dp[j],t);
			}
			while(l--)
			{	if(j>=vt[0][i].w+vt[a[i]][l].w)
				{
				int t=dp[j-vt[0][i].w-vt[a[i]][l].w]+vt[0][i].w*vt[0][i].v+vt[a[i]][l].w*vt[a[i]][l].v;
				dp[j]=max(dp[j],t);
				}
			}
		}
	}
	cout<<dp[n]<<endl;
	
	
	return 0;
}

  

 

题目二:

https://www.luogu.org/problemnew/show/P1280

在同一时刻,有多个方案的话,就会存在最优决策问题,而你发现不管选哪个,前面时间段最优肯定是不会变的,这种像是没有“前效性”,而不同的选择会到达之后不同的时间点,就是以时间点为状态的逆推DP(或记忆化搜索)

 

#include<iostream>
#include<vector>
using namespace std;
struct NODE{
	int l,r;
}e[10005];
int dp[10005];
vector<int>vt[10005];
int main()
{
	
	int n,k;
	cin>>n>>k;
	for(int i=1;i<=k;i++)
	{
		scanf("%d%d",&e[i].l,&e[i].r);
		vt[e[i].l].push_back(i);
	}
	dp[n+1]=0;
	for(int i=n;i>=1;i--)
	{	int l=vt[i].size();
		if(l==0) dp[i]=dp[i+1]+1;
		else
		{	dp[i]=0;
			for(int k=0;k<l;k++)
			{
				dp[i]=max(dp[i],dp[i+e[vt[i][k]].r]);
			}
		}
		
	}
	cout<<dp[1]<<endl;
	return 0;
}

  

 

题目三:

https://www.luogu.org/problemnew/show/P1417

说到决策,就不难想到贪心,这个题就是贪心+01背包

因为这题在不同的时间点或者说先做或后做某件事,产生的贡献是不一样,这就和背包不一样

假设两个物品x,y

先x:a[x]-(p+c[x])*b[x]+a[y]-(p+c[x]+c[y])*by

先y:a[y]-(p+c[y])*b[y]+a[x]-(p+c[y]+c[x])*bx

可知:c[x]*b[y]<c[y]*b[x].时,先选x是优于先选y的。

所以,先排序,后01背包

#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
ll dp[100005];
struct NODE{
    ll a,b,c;
}e[200];
bool cmp(struct NODE x,struct NODE y)
{
    return x.c*y.b<x.b*y.c;
}
int main()
{    int T,n;
    
    cin>>T>>n;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&e[i].a);
    }
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&e[i].b);
    }
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&e[i].c);
    }
    sort(e+1,e+1+n,cmp);
    memset(dp,-1,sizeof dp);
    dp[0]=0;
    for(ll i=1;i<=n;i++)
    {
        for(ll j=T;j>=0;j--)
        {
             if (dp[j] != -1 && j + e[i].c <= T)
    dp[j + e[i].c] = max(dp[j + e[i].c], dp[j] + e[i].a - (j + e[i].c) * e[i].b);

        }
    }
    ll mx=0;
    for(int i=0;i<=T;i++)
    mx=max(dp[i],mx);
    cout<<mx<<endl;
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/lnu161403214/p/8922462.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值