zoukankan      html  css  js  c++  java
  • 【题解】 P1651 塔

    解法一:

    f[i][j][k] = 0/1表示使用前i个水晶,第一个塔高j,第二个塔高k,是否可行。
    决策:第i个水晶放不放,放在哪。
    f[i][j][k] = f[i - 1][j][k] || f[i - 1][j - a[i]][k] || f[i - 1][j][k - a[i]]

    解法二:

    f[i][j] 表示从前i个积木中选,两组高度差为j, 高度较小的那一个塔高度最大是多少。

    当两组双塔的高度差一样时,我们只将更高的那一组存入状态而舍弃更矮的那一组。如前三个积木3,5,7,两组状态的塔分别为:3,5和5,7时,我们只存f[3][2] = 5,对以后的状态转移无错误影响。

    决策:

    第i个水晶放不放,放在哪,放完之后两塔的高低关系是否发生改变。

    转移(注意逆向思维):

    第i个水晶不放,f[i][j] = f[i - 1][j]
    第i个水晶放上之后是矮塔,之前肯定也是矮塔,之前高度差更大,f[i][j] = f[i - 1][j + h[i]] + h[i]
    第i个水晶放上之后是高塔,之前也是高塔,之前高度差要小一些,矮塔高度不变,f[i][j] = f[i - 1][j - h[i]]
    第i个水晶放上之后是高塔,之前是矮塔,原高塔是现矮塔,原高塔高度为原矮塔高度加高度差,f[i][j] =f[i - 1][h[i] - j] + h[i] - j

    方程:

    f[i][j] = max(f[i - 1][j], f[i - 1][j + h[i]] + h[i], f[i - 1][j - h[i]], f[i - 1][h[i] - j] + h[i] - j)

    code

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<cstdlib>
    using namespace std;
    const int maxn = 55, maxh = 500010;
    int h[maxn], n, ans;
    int sum, f[maxn][maxh], now;
    int main(){
        scanf("%d", &n);
        memset(f, -1, sizeof(f));
        cin >> h[1];
        f[1][0] = 0;
        f[1][h[1]] = 0;
        now = h[1];
        for(int i = 2; i <= n; i++){
        	scanf("%d", &h[i]);
        	now += h[i];
        	for(int j = 0; j <= now; j++){
        		f[i][j] = f[i - 1][j];
    //    		cout << j << " ";
        		if(f[i - 1][j + h[i]] != -1 && f[i - 1][j + h[i]] + h[i] <= now / 2){
    //    			cout << "first " ;
    	    		f[i][j] = max(f[i][j], f[i - 1][j + h[i]] + h[i]);// 矮-矮
    	    	}
    			if(j >= h[i] && f[i - 1][j - h[i]] != -1 && f[i - 1][j - h[i]] <= now / 2){
    //				cout << "second " ;
    				f[i][j] = max(f[i][j], f[i - 1][j - h[i]]);//高-高 
    			}
    			if(h[i] - j > 0 && f[i - 1][h[i] - j] != -1 && f[i - 1][h[i] - j] + h[i] - j){
    //				cout << "third ";
    				f[i][j] = max(f[i][j], f[i - 1][h[i] - j] + h[i] - j);//高-矮 
    			}
    //			cout << f[i][j] << endl;
    		}
    	}
    
    	ans = max(ans, f[n][0]);
    
    	if(ans != 0)	cout << ans << endl;
    	else
    		cout << -1 << endl;
    	return 0;
    }
    
  • 相关阅读:
    Error 500curl_setopt(): CURLOPT_SSL_VERIFYHOST no longer accepts the value 1, value 2 will be used i
    解决Apache提示没有权限访问的问题
    【服务器】本地运行成功,但服务器上运行却显示错误500
    CentOS 7中PHP配置文件php.ini的放在哪个位置
    用yum快速搭建LAMP平台
    redis 在32位系统安装以及使用
    CentOS7查看和关闭防火墙
    CENTOS7下安装REDIS
    在centos和redhat上安装docker
    Annotation 注解
  • 原文地址:https://www.cnblogs.com/ZhengkunJia/p/13615215.html
Copyright © 2011-2022 走看看