zoukankan      html  css  js  c++  java
  • 【题解】「P1504」积木城堡

    这题是01背包((DP))

    如何判断要拆走那个积木,首先定义一个(ans)数组,来存放这对积木能拼成多高的,然后如果(ans_i = n)那么就说明这个高度的积木可以。

    话不多说,上代码!

    #include<cstdio> //从最小高度~1枚举, 如果能恰好达到这个高度(即用它有的积木恰好能拼出)有n个城堡
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    int n, len, min_high = 2e9;
    //n表示城堡数,len表示每块立方体积木的棱长, min_high表示所有城堡初始高度最小值 
    int w[10005],ans[10005]; //设ans[i]表示i能被多少组w[1..n]凑成,当dp[i]==true时,ans[i]++
    //w[i]表示组成这座城堡的第i块积木的棱长 
    bool dp[10005]; //dp[i]表示能否使用当前的w[1..n]相加得到i
    /* 有n件物品(积木),每件物品体积(积木的棱长)为w[i], 价值(积木的棱长)为w[i]。
    有容量(城堡高度)为 V 的背包(城堡)。求在容量(城堡高度)允许的范围下,背包装入物品的价值和(积木的棱长和)有哪些可能值。*/ 
    
    
    int main()
    {
    	scanf("%d", &n);
    	for(int k = 1; k <= n; k++)
    	{
    		memset(dp, 0, sizeof(dp));
    		int cnt = 1, high = 0; //cnt表示每座城堡含积木的块数,high表示每座城堡的初始高度 
    		while(1)
    		{
    			scanf("%d", &w[cnt]); //len表示组成这座城堡的每块积木的棱长
    			if(w[cnt] == -1) break;
    			high += w[cnt];
    			cnt++;
    		}
    		dp[0] = 1; // dp[0] = 1表示能使用当前的w[1..n]相加得到高度0
    		min_high = min(min_high, high); //求出所有城堡初始高度最小值 
            for(int i = 1; i < cnt; i++) //对每座城堡从1~g去枚举每一块积木 
    			for(int j = high; j >= w[i]; j--)
    				dp[j] = dp[j] || dp[j-w[i]]; //01背包变形,即动态转移方程
    		for(int i = high; i >= 1; i--)
            	if(dp[i] == true) ans[i]++; //统计高度i出现次数
    	}
        for(int i = min_high; i >= 1; i--) //从最小高度~1枚举
    		if(ans[i] == n) //如果能恰好达到这个高度(即用它有的积木恰好能拼出)有n个城堡
    		{
    			printf("%d
    ", i);  
    			return 0;
    		}
    	printf("0
    ");
        
    	return 0;
    }
    

    (Bye Bye!)

  • 相关阅读:
    SQL 函数:Aggregate、Scalar函数介绍
    SQL 用于各种数据库的数据类型:MySQL、SQLsever
    SQL 通用数据类型解析
    SQL NULL 函数:使用方法及案例剖析
    SpringBoot的配置文件
    SpringBoot简介及快速入门
    本地仓库和远程仓库分支回退到指定的历史版本(idea)
    maven配置阿里云镜像仓库
    SSM三大框架整合-分模块版本
    Java程序调用Oracle存储过程和存储函数
  • 原文地址:https://www.cnblogs.com/-TNT-/p/solution-p1504.html
Copyright © 2011-2022 走看看