当前位置: 首页 > news >正文

【Foreign】咏叹 [模拟退火]

咏叹

Time Limit: 100 Sec  Memory Limit: 256 MB

Description

  有n根木棍,第i根长度为ai。你要贴着墙围出一个矩形区域,木棍围成的矩形边缘必须平行或垂直于墙,且又一边必须利用墙。你可以把至多1根木棍劈成两根(不一定要在整数位置)。最大化矩形面积。

Input

  包含多组数据。每组数据第一行一个整数n,第二行n个整数ai。

Output

  输出面积最大的矩形与墙壁平行的那条边的长度(显然是一个整数),若有多个最优解输出与墙壁平行的那条边最长的。

Sample Input

    3
    3 3 3
    4
    4 4 4 4

Sample Output

  6
  8

HINT

  对于10%的数据,n=2。
  对于30%的数据,n<=15。
  对于50%的数据,n<=32。
  对于另外20%的数据,ai<=100。
  对于100%的数据,2<=n<=40,1<=ai<=10^9,数据不超过10组。

Solution

  首先,必然是全部木棍都用上的时候最优,对于n=2的时候,显然就是分三种情况讨论一下就好了。

  然后我们从n=2的情况拓展。发现,其实可以把多个木棍并在一起,使其变为n=2的情况,然后讨论。那么现在答案只和两段的长度有关了。

  但是直接暴力搜索是O(2^40)的,显然不行,我们考虑分为两部分来搜索,搜索前n/2个,和后n/2个,表示选不选得到的价值,现在效率是O(2*2^20)。

  然后怎么得到答案呢?显然:如果我们设宽为x,则长为tot-2x(tot为总长),那么这是一个二次函数,必然有峰值。

  所以我们大胆猜测,我们确定了一半,另外一半使得其答案最优的话也可能满足有峰值的性质

  然后我们固定一半,另一半运用模拟退火求解即可!

Code

  1 #include<iostream>  
  2 #include<string>  
  3 #include<algorithm>  
  4 #include<cstdio>  
  5 #include<cstring>  
  6 #include<cstdlib>  
  7 #include<cmath>
  8 #include<ctime>
  9 using namespace std; 
 10 typedef long long s64;
 11 
 12 const int ONE = 2100000;
 13 
 14 int T,n;
 15 int a[45],top1,top2;
 16 s64 Stk1[ONE],Stk2[ONE];
 17 s64 Square, Ans, tot, RE;
 18 
 19 int get() 
 20 {
 21         int res=1,Q=1;  char c;
 22         while( (c=getchar())<48 || c>57)
 23         if(c=='-')Q=-1;
 24         if(Q) res=c-48; 
 25         while((c=getchar())>=48 && c<=57) 
 26         res=res*10+c-48; 
 27         return res*Q; 
 28 }
 29 
 30 s64 Get(s64 width,s64 length)
 31 {
 32         s64 res = length * width;
 33         
 34         if(res > Square || (res==Square && length>Ans))
 35             Square = res, Ans = length;
 36         return res;
 37 }
 38 
 39 s64 Check(s64 A,s64 B)
 40 {
 41         if(A > B) swap(A,B);
 42         s64 res = 0;
 43         res = max(res,Get(A, B-A));
 44         res = max(res,Get(A/2,B));
 45         res = max(res,Get(B/2,A));
 46         return res;
 47 }
 48 
 49 void Dfs1(s64 val,int T)
 50 {
 51         if(T>n/2) {Stk1[++top1] = val; return;}
 52         Dfs1(val,T+1);    Dfs1(val+a[T],T+1);
 53 }
 54 
 55 void Dfs2(s64 val,int T)
 56 {
 57         if(T>n) {Stk2[++top2] = val; return;}
 58         Dfs2(val,T+1);    Dfs2(val+a[T],T+1);
 59 }
 60 
 61 s64 Judge(int i,int j)
 62 {
 63         return Check(Stk1[j] + Stk2[i],tot - Stk1[j] -Stk2[i]);
 64 }
 65 
 66 double Random() {return (double)rand()/RAND_MAX;}
 67 void Deal(int id)
 68 {
 69         int Now = top2/2;
 70         double Temper = top2/3;
 71         while(Temper >= 1)
 72         {
 73             int A = Now + (int)Temper * (Random()*2.0-1);
 74             if(A<=0) A = (int)Temper * Random() + 1;
 75             s64 dE = Judge(A,id) - Judge(Now,id);
 76             if(dE > 0 || Random()<=exp(dE)) 
 77                 Now = A;
 78             if(Temper > top2 / 2) Temper *= 0.1;
 79             Temper *= 0.75;
 80         }
 81         Judge(Now-1,id);    Judge(Now+1,id);
 82 }
 83 
 84 void Solve2()
 85 {
 86         top1 = top2 = tot = 0;
 87         for(int i=1;i<=n;i++) a[i]=get(),a[i]*=2,tot += a[i]; 
 88         Dfs1(0,1);        sort(Stk1+1,Stk1+top1+1);    top1 = unique(Stk1+1,Stk1+top1+1)-Stk1-1;
 89         Dfs2(0,n/2+1);    sort(Stk2+1,Stk2+top2+1);    top2 = unique(Stk2+1,Stk2+top2+1)-Stk2-1;
 90         Ans = Square = 0;
 91         
 92         for(int i=1;i<=top1;i++)
 93             Deal(i);
 94         
 95         
 96         printf("%lld\n",Ans/2);
 97 }
 98 
 99 void Dfs(s64 A,s64 B,int T)
100 {
101         if(T>n)
102         {
103             Check(A,B);
104             return;
105         }
106         Dfs(A+a[T],B,T+1);
107         Dfs(A,B+a[T],T+1);
108 }
109 
110 void Solve1()
111 {
112         Ans = Square = 0;
113         for(int i=1;i<=n;i++) a[i]=get(),a[i]*=2;
114         Dfs(0,0,1);
115         printf("%lld\n",Ans/2);
116 }
117 
118 int main()
119 {
120         srand(time(0));
121         while(scanf("%d",&n)!=EOF)
122         {
123             if(n <= 25) Solve1();
124             else Solve2(); 
125         }
126 }
View Code

 

转载于:https://www.cnblogs.com/BearChild/p/6683327.html

相关文章:

  • css的伪类选择器的使用
  • 待字闺中之快排单向链表;leetcode之Sort List
  • 打造比Dictionary还要快2倍以上的字查找类
  • nginx调优操作之nginx隐藏其版本号
  • 图片视频制作方法
  • Rsyslog日志服务搭建
  • 2017年北京下半年软考网上报名时间和网址
  • 各大搜索引擎智能提示API(jsonp实现跨域自动补全建议)
  • SpringMVC传入参数
  • Vue SSR 从入门到 Case Study
  • Android学习笔记进阶20 之得到图片的缩略图
  • 解决面板里没有network manager图标的问题 ,也就是在桌面环境下,没有那个网络图标...
  • python类的继承、封装和多态
  • SQLite 索引(Index)
  • java zip 压缩与解压
  • 【翻译】babel对TC39装饰器草案的实现
  • 【附node操作实例】redis简明入门系列—字符串类型
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • docker python 配置
  • es6要点
  • java 多线程基础, 我觉得还是有必要看看的
  • leetcode386. Lexicographical Numbers
  • MySQL用户中的%到底包不包括localhost?
  • PAT A1120
  • V4L2视频输入框架概述
  • Web设计流程优化:网页效果图设计新思路
  • 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1
  • 关于for循环的简单归纳
  • 技术:超级实用的电脑小技巧
  • 聊聊hikari连接池的leakDetectionThreshold
  • 前端
  • 思考 CSS 架构
  • 微信支付JSAPI,实测!终极方案
  • 新手搭建网站的主要流程
  • 【云吞铺子】性能抖动剖析(二)
  • 正则表达式-基础知识Review
  • #DBA杂记1
  • $.each()与$(selector).each()
  • (二)JAVA使用POI操作excel
  • (附源码)ssm失物招领系统 毕业设计 182317
  • (附源码)计算机毕业设计SSM疫情社区管理系统
  • (一)WLAN定义和基本架构转
  • (转载)Linux 多线程条件变量同步
  • (转载)跟我一起学习VIM - The Life Changing Editor
  • .NET CORE 第一节 创建基本的 asp.net core
  • .NET Core跨平台微服务学习资源
  • .NET Framework与.NET Framework SDK有什么不同?
  • .Net IE10 _doPostBack 未定义
  • .net 使用ajax控件后如何调用前端脚本
  • .NET 事件模型教程(二)
  • .net6使用Sejil可视化日志
  • .net专家(张羿专栏)
  • ??javascript里的变量问题
  • [ 攻防演练演示篇 ] 利用通达OA 文件上传漏洞上传webshell获取主机权限
  • [Angular 基础] - 自定义指令,深入学习 directive