zoukankan      html  css  js  c++  java
  • 【洛谷 P1651】 塔 (差值DP)

    题目链接
    题意:(n)个木块放到两个塔里,每个木块可放可不放,使得两塔高度相同且高度最大,求最大高度。
    这个差值(DP)的思维难度还是很大的,没想出来,我就打了一个(dfs)骗了好像(20)还是(30)分吧(看来搜索也写挂)。
    正解是(DP)(f[i][j])表示前(i)块木块使得两个塔的高度差为(k)时高度最大的那个是什么(神奇的状态)
    那么无非就(4)种情况:
    1、第(i)块不放:(f[i][j]=f[i-1][j])
    2、第(i)块放到矮的上面,矮的仍然矮:(f[i][j]=f[i-1][j+a[i]])
    3、第(i)块放到高的上面,高的当然高:(f[i][j]=f[i-1][j-a[i]]+a[i])
    4、第(i)块放到矮的上面,矮的变高的:(f[i][j]=f[i-1][a[i]-j]+j)
    可以发现,(f[i])的取值仅与(f[i-1])有关,于是第一维是可以滚掉的。

    #include <cstdio>
    #include <cstring>
    #define Open(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout);
    #define Close fclose(stdin);fclose(stdout);
    const int MAXN = 55;
    const int MAX = 500010;
    int dp[MAX][2];
    inline int max(int a, int b){
        return a > b ? a : b;
    }
    int n, s[MAXN], sum;
    int main(){
    	Open("tower");
    	scanf("%d", &n);
    	for(int i = 1; i <= n; ++i)
    		scanf("%d", &s[i]), sum += s[i];
    	memset(dp, 128, sizeof dp);
    	dp[0][0] = dp[0][1] = 0;
    	for(int i = 1; i <= n; ++i)
           for(int j = sum; ~j; --j){
              dp[j][i%2] = dp[j][!(i%2)];
              if(j + s[i] <= sum) dp[j][i%2] = max(dp[j][i%2], dp[j + s[i]][!(i%2)]);
              if(j - s[i] >= 0) dp[j][i%2] = max(dp[j][i%2], dp[j - s[i]][!(i%2)] + s[i]);
              if(j < s[i]) dp[j][i%2] = max(dp[j][i%2], dp[s[i] - j][!(i%2)] + j);
           }
    	printf("%d
    ", !dp[0][n%2] ? -1 : dp[0][n%2]);
    	Close;
    	return 0;
    }
    
    
  • 相关阅读:
    Java实现数组去除重复数据的方法详解
    java枚举和constant使用区别
    如何健壮你的后端服务
    entityframework学习笔记--001
    MongoDB配置服务--MongoDB安装成为windows服务
    MongoDB基础入门003--使用官方驱动操作mongo,C#
    MongoDB基础入门002--基本操作,增删改查
    MongoDB基础入门001--安装
    webapi的返回类型,webapi返回图片
    C#异步下载文件--基于http请求
  • 原文地址:https://www.cnblogs.com/Qihoo360/p/9660248.html
Copyright © 2011-2022 走看看