POJ 1190 生日蛋糕
来源:互联网 发布:莎莎源码网 编辑:程序博客网 时间:2024/05/18 03:58
呵呵,这道题弄死我。。。
我觉得吧,凡事不能急于求成,比如这道经典的剪枝+搜索,我就先查的题解,看了各种剪枝方法踌躇满志,结果花了两个小时写的剪枝把自己都搞晕了。。。应该先有正确的搜索方法再谈剪枝不是吗,所以我决定先用朴素的搜索做一下
#include<stdio.h>#include<math.h>int n, m;int temp_s = 99999;void search( int a, int r, int h, int v, int s);int main(void){int root;scanf("%d%d", &n, &m);root = sqrt(n);// 这是我设置的一个上限,事实上不需要从n-1开始枚举 search( m, root, root, 0, 0); // 在这里如果进入递归的参数a值是1,再向上判断就会丢失最优解 printf("%d", temp_s);return 0;}void search( int a, int r, int h, int v, int s){int max_h, i, j;if( a <= 0){if( v == n && temp_s > s){temp_s = s;}return;}for( i = r - 1; i >= a; i--){max_h = ( n - v) / ( i * i);for( j = max_h; j >= a; j--){if( v + i * i * j > n){ // 一个比较简单的优化,大于原体积就不用枚举了 break;}if( a == m) s = i * i;search( a-1, i, j, v+i*i*j, s+2*i*j); // 这里是作为新手的我一开始没有想到的(事实上这里的v,s随i,j变化,所以作为参数传递很合理)}}}抱着侥幸的心理提交了一下,呵呵,果真超时了
好吧认命进行剪枝
根据http://www.xuebuyuan.com/738138.html 查的,初步确定以下几个剪枝想法
1、第a层的 r 和 h 至少是 a;可以求出每层的最小体积和表面积,如果a-1层的 v , s 使剩余体积小于合法能够达到的最小体积,则说明a-1层体积过小,由于是递减循环,所以这说明这一个分支已经可以不用继续搜索了
2、如果剩余体积加最小体积大于标准体积,那么这个分支也不用继续搜索了
3、如果在没有到递归底部表面积就大于现有的最优解,那么这个分支也不用继续搜索了
4、如果这一次加下一次的最小表面积大于现有最优解,那么这个分支也不用继续搜索了(可以和4合并)
#include<stdio.h>#include<math.h>#define min(a,b) (a > b ? b : a) // 这里的写法挺好的,免得再写一个函数了 int n, m;int temp_s = 999999;// temp_s 设置一个很大的值 int min_v[25], min_s[25]; void search( int a, int r, int h, int v, int s);// 搜索函数 void minset( int m);// 求最小值函数 int main(void){int root;while(~scanf("%d%d", &n, &m)){ // 一个确保连续输入的语句 ~按位取反 minset(m);root = sqrt(n);search( m, root, root, 0, 0); // 这里root应该能缩小一些搜索范围 // 题意是一个倒三角形,所以从这里开始相当于一个从顶向下的递归(顶最大,越向下越小)if( temp_s == 99999) temp_s = 0; // 这里表示没有可能值 printf("%d\n", temp_s);}return 0;}void minset( int m){int i;min_v[0] = min_s[0] = 0;for( i = 1; i <= m; i++){min_v[i] = min_v[i-1] + i*i*i; // 每一层的体积最小值 min_s[i] = min_s[i-1] + 2*i*i; // 每一层的表面积最小值 }}void search( int a, int r, int h, int v, int s){int max_h, i, j;if( a == 0){if( v == n && temp_s > s) temp_s = s; // 若小于最优解就替换 return;}if( s + min_s[a-1] >= temp_s || v + min_v[a-1] > n || 2*(n-v)/r + s >= temp_s) return;// 第一个条件即判断:若此次体积加最小体积大于标准体积,放弃这个分支// 第二个条件即判断:若此次加下一次的最小表面积大于现有最优解,放弃这个分支// 第三个条件即判断:若剩余体积所需的最小表面积加已有的表面积大于最优解,放弃这个分支。貌似没有这个判断就会超时 // <span style="color:#3333FF;">我觉得这个题的剪枝包括两个方面,第一个方面是对下一个状态进行判断,第二个方面是对远景状态进行判断,其中第二个方面能筛下去很多很多不必要分支</span>for( i = r - 1; i >= a; i--){max_h = min((n-v-min_v[a-1]) / ( i * i), h-1);// 求h-1和 剩余体积与最小体积之差 之间的最小值——<span style="color:#FF0000;">没有这个会WA...并不知道为什么</span> for( j = max_h; j >= a; j--){if( a == m) s = i * i; // 还有一个圆的面积 search( a-1, i, j, v+i*i*j, s+2*i*j); // v,s作为参数传递 }}}
【恩,头一个半自主完成的搜索+剪枝题,虽然前前后后包括读题和写博客总结花了我将近五个小时,超时WA了无数次,但是做完还是很高兴的,AC的那一刹感觉那一切都值了】
0 0
- poj 1190 生日蛋糕
- poj 1190 dfs(生日蛋糕)
- POJ 1190 生日蛋糕
- POJ 1190 生日蛋糕
- poj 1190 生日蛋糕
- 【DFS】poj 1190 生日蛋糕
- POJ 1190 生日蛋糕
- POJ 1190 生日蛋糕
- [POJ 1190] 生日蛋糕
- poj 1190 生日蛋糕
- POJ 1190 生日蛋糕
- poj 1190 生日蛋糕
- 生日蛋糕POJ 1190
- POJ 1190 生日蛋糕
- poj 1190 生日蛋糕
- POJ 1190 生日蛋糕
- POJ 1190 生日蛋糕
- poj 1190 生日蛋糕
- 设计模式(一)之适配器模式
- Android源码学习(5)Android编译系统之envsetup.sh
- git报错fatal: HTTP request failed
- C/C++赋值中的退化规则
- Nginx Http负载均衡
- POJ 1190 生日蛋糕
- 如何使用AFNetworking进行上传图片
- 安卓实习期间整理知识点(十二)
- JSONModel解析数据成Model
- Xcode6文档注释下载地址
- PHP设计模式 三 (适配器 代理模式 数据映射)
- JS技巧:兼容性导出表格为Excel文件
- linux命令实现:whoami
- android shape的使用详解以及常用效果(渐变色、分割线、边框、半透明阴影效果等)