zoukankan      html  css  js  c++  java
  • 洛谷 P1651 塔

    题目传送门

    一道dp,但我没推出方程,只好写记忆化搜索+剪枝.
    主要说一下为什么从小到大排序,如果大的块被选择且最终得出符合题意的答案,那么后面很多状态都会被剪掉,因为答案越搜越小(应该是).

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<map>
    #include<algorithm>
    
    using namespace std;
    
    int n,h[51],ans = -1,sum[51];
    map<int,map<int,map<int,bool> > > s;
    
    inline int max(int a,int b) {
    	if(a > b) return a;
    	return b;
    }
    
    inline void dfs(int d,int lena,int lenb) {
    	if(d == n + 1) {
    		if(lena == lenb && lena != 0) ans = max(lena,ans);
    		return ;
    	}
    	if(s[d][lena][lenb] == 1) return ;
    	s[d][lena][lenb] = 1;
    	if(lena > sum[n] / 2) return ;
    	if(lenb > sum[n] / 2) return ;
    	if(lena + sum[n] - sum[d-1] < lenb) return ;
    	if(lenb + sum[n] - sum[d-1] < lena) return ;
    	if(lena + sum[n] - sum[d-1] == lenb && lenb != 0) {
    		ans = max(ans,lenb);
    		return ;
    	}
    	if(lenb + sum[n] - sum[d-1] == lena && lena != 0) {
    		ans = max(ans,lena);
    		return ;
    	}
    	if(ans >= lena + sum[n] - sum[d-1]) return ;
    	if(ans >= lenb + sum[n] - sum[d-1]) return ;
    	if(ans * 2 >= lena + lenb + sum[n] - sum[d-1]) return ;
    	dfs(d + 1,lena,lenb + h[d]);
    	dfs(d + 1,lena + h[d],lenb);
    	dfs(d + 1,lena,lenb);
    	return ;
    }
    
    inline bool cmp(int a,int b) {
    	return a > b;
    }
    
    int main() {
    	scanf("%d",&n);
    	for(int i = 1;i <= n; i++)
    		scanf("%d",&h[i]);
    	sort(h+1,h+n+1,cmp);
    	for(int i = 1;i <= n; i++)
    		sum[i] += sum[i-1] + h[i];
    	dfs(1,0,0);
    	printf("%d",ans);
    	
    	return 0;
    }
    
  • 相关阅读:
    asp.net 实现pdf、swf等文档的浏览
    VS NuGet加载本地程序包
    《大型网站技术架构》读书笔记
    全排列组合算法
    GDI+绘制半圆按钮
    oracle dblink 查询 tns:无法解析指定的连接标识符
    最少有多少鸡蛋(求最小公倍数)
    杨辉三角
    Android开发面试题(一)
    2015年11月系统架构设计师案例分析题
  • 原文地址:https://www.cnblogs.com/lipeiyi520/p/13663325.html
Copyright © 2011-2022 走看看