1 solutions

  • 1
    @ 2024-6-12 16:59:51

    题意

    一个要求凑满的01背包,凑不满就输出最大化价值的体积。

    思路

    首先先把01背包写好。如果01不熟的可以先把采药之类的题目A掉再回来。

    然后就是爆改。

    首先我们要怎样标记凑不出来呢?

    凑不出来有两种情况:

    1. 没有触及。
    2. 被凑不出来的触及。

    为什么感觉有点像递归啊喂!

    所以我们初始化为负无限,不可触及就会保留负无限。

    那如果被凑不出来的碰了呢?很简单,加一个特判,如果碰完发现它还是负数,说明碰它的是负无限,就把它标回负无限。

    最后判断一下,如果答案为负数就找最大。

    代码

    #include<iostream>
    #define maxs 0x7fffffff//好看,主要是为了好看。 
    using namespace std;
    int f[int(2e6)];//有点大,开在外面 
    int main(){
    	int n(0),v(0);
    	cin>>n>>v;
    	struct{int v;int w;}a[n+1];//清爽的a 
    	for(int i(1);i<=n;i++)
    		cin>>a[i].v;
    	//最讨厌它分开的一集  --|二二二二二二>
    	for(int i(1);i<=n;i++)
    		cin>>a[i].w;
    	fill(f,&f[v+1],-maxs);//标最大值,以区分价值为0和无法凑出的区别。 
    	f[0]=0;//空间为0就当然没有价值啦^_^ 
    	for(int i(1);i<=n;i++)//状态永远是被压掉的内个,状态放外面 
    		for(int j(v);j>0;j--)
    /*观察二维的状态转移方程得知,需要使用前面的,所以前面的暂时不能改。*/ 
    			if(j>=a[i].v){//如果塞得下 
    				f[j]=max(f[j],f[j-a[i].v]+a[i].w);//看看谁比较大 
    				if(f[j]<0)
    					f[j]=-maxs;
    /*无限永恒!(bushi)其实是为了防止屡次上升变成非负数。*/ 
    			}
    	if(f[v]>=0)//凑得出来 
    		cout<<f[v];
    	else{//凑不出来就会保持原来的无限 
    		int maxn(-maxs),maxi(0);
    		for(int i(1);i<=v;i++)//这还要教就回去练<<A+B problem>>吧。 
    			if(f[i]>maxn){
    				maxn=f[i];
    				maxi=i;
    			}
    		cout<<maxi;
    	}
    }
    
    • 1

    Information

    ID
    1102
    Time
    1000ms
    Memory
    256MiB
    Difficulty
    8
    Tags
    (None)
    # Submissions
    40
    Accepted
    7
    Uploaded By