• 决策型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
  • 相关阅读:
    Django异步与定时任务Celery
    SkyWalking 分布式追踪系统
    SharePoint 2010 硬件详细需求
    使用SharePoint 2010 客户端对象模型进行文档库及文档的操作
    SharePoint 2010 部署架构
    【git】项目添加.gitignore忽略.idea文件夹
    Android 横屏切换竖屏Activity的生命周期(转)
    经过完整测试的农历公历相互转换
    TZ ERP项目的随想
    C#加密与解密
  • 原文地址:https://www.cnblogs.com/lnu161403214/p/8922462.html
Copyright © 2020-2023  润新知