zoukankan      html  css  js  c++  java
  • 决策型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
  • 相关阅读:
    SQLite的SQL语法
    C/C++中各种类型int、long、double、char表示范围(最大最小值)
    君子性非异也,善假于物也
    简单工厂模式
    Linux下通配符总结
    Readprocessmemory使用方法
    C++ 清空消息队列
    一周自学动态站点设计
    iOS 8.0正式公布啦
    What is the difference between JRE,JVM and JDK?
  • 原文地址:https://www.cnblogs.com/lnu161403214/p/8922462.html
Copyright © 2011-2022 走看看