http://poj.org/problem?id=3628
Description
Farmer John recently bought another bookshelf for the cow library, but the shelf is getting filled up quite quickly, and now the only available space is at the top.
FJ hasNcows (1 ≤N≤ 20) each with some height ofHi(1 ≤Hi≤ 1,000,000 - these are very tall cows). The bookshelf has a height ofB(1 ≤B≤S, whereSis the
sum of the heights of all cows).
To reach the top of the bookshelf, one or more of the cows can stand on top of each other in a stack, so that their total height is the sum of each of their individual heights. This total height must be no less than the height of the bookshelf in order for
the cows to reach the top.
Since a taller stack of cows than necessary can be dangerous, your job is to find the set of cows that produces a stack of the smallest height possible such that the stack can reach the bookshelf. Your program should print the minimal 'excess' height between
the optimal stack of cows and the bookshelf.
Input
* Line 1: Two space-separated integers:NandB
* Lines 2..N+1: Linei+1 contains a single integer:Hi
Output
* Line 1: A single integer representing the (non-negative) difference between the total height of the optimal set of cows and the height of the shelf.
Sample Input
5 16
3
1
3
5
6
Sample Output
1
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
public class Test3628 {
static int n, b;
static int[] h;
static boolean[] used;
static int min = Integer.MAX_VALUE;
public static void main(String[] args) throws Exception {
BufferedReader read = new BufferedReader(new InputStreamReader(
System.in));
String[] s = read.readLine().split(" ");
n = Integer.parseInt(s[0]);
h = new int[n];
used = new boolean[n];
b = Integer.parseInt(s[1]);
for (int i = 0; i < n; i++) {
h[i] = Integer.parseInt(read.readLine());
}
Arrays.sort(h);
search(0, 0);
System.out.println(min);
}
public static boolean search(int sum, int deep) {
if (sum >= b) {
if (sum - b < min) {
min = sum - b;
}
return true;
}
for (int i = deep; i < n; i++) {
if (used[i]) {
continue;
}
used[i] = true;
if (search(sum + h[i], i + 1)) {
used[i] = false;
break;
}
used[i] = false;
}
return false;
}
}
总结:N较小,max较大时,应该用递归或dps求解。
N较大,MAX小时,用01背包求解。 或改进版的 fast版递归求解。
//关于各种方法的测试数据
public class Poj3628 {
static int arr[] = {3,44,14,57,11,60,170,66,22,36,88,140,230,111,214,325,444,666,745,233};
static int max = 894;
static int n; //数组长度
static int opt = -1; //最后的结果
static int cnt = 0; //记录每个方法调用次数
static int optArr[][]; //存储中间的最优结果
static int packOpt[];
static int M = 100; //循环测试次数
/**
* dfs深度优先搜索做。
* @param sum 求得的中间结果
* @param index 当前的数组下标
*/
private static void dps(int sum, int index){
//System.out.println(sum + " " +index);
cnt ++;
if(index == n){ //得到最终结果. 注意:这里应该是到n才结束
if(sum > opt)
opt = sum;
return;
}
dps(sum, index + 1); //不使用index当前这个数
if(sum + arr[index] <= max){ //如果index当前这个数可以用
dps(sum + arr[index], index + 1);
}
}
/**
* 由后向前递推
* @param remain 当前可用的容量
* @param index
* @return 在当前容量下 装index之前的数, 所能装下的最大值
*/
private static int fun(int remain, int index){
cnt ++;
if(index < 0) //说明递推完毕。即 fun(remain,-1) = 0;则 fun(remain-arr[0],0) = arr[0];
return 0;
int a = fun(remain,index-1);
if(remain - arr[index] >= 0){ //即当前这个数可用
int b = fun(remain - arr[index],index-1) + arr[index];
return Math.max(a, b); //比较,得出较大的数
}
else //不用当前这个数
return a;
}
private static int fastFun(int remain, int index){
cnt ++;
if(index < 0)
return 0;
if(optArr[remain][index] > 0)
return optArr[remain][index];
int a = fastFun(remain,index-1);
if(remain - arr[index] >= 0){ //即当前这个数可用
int b = fastFun(remain - arr[index],index-1) + arr[index];
return (optArr[remain][index] = Math.max(a, b) ); //比较,得出较大的数
}
else //不用当前这个数
return (optArr[remain][index] = a);
}
private static void pack01(){
for(int i=0; i<n; i++){
for(int j=max; j>=arr[i]; j--){
cnt++;
packOpt[j] = Math.max(packOpt[j-arr[i]] + arr[i], packOpt[j]);
}
}
}
public static void main(String[] args) {
cnt = 0;
n = arr.length;
Long start = System.currentTimeMillis();
for(int i=0; i<M; i++){
dps(0,0);
}
Long end = System.currentTimeMillis();
System.out.println("dps(0,0)调用次数:" + cnt);
System.out.println(opt);
System.out.println("时间:" + (end-start));
cnt = 0;
int result = 0;
start = System.currentTimeMillis();
for(int i=0; i<M; i++){
result = fun(max,n-1);
}
end = System.currentTimeMillis();
System.out.println("fun(max,n-1))调用次数:" + cnt);
System.out.println(result);
System.out.println("时间:" + (end-start));
cnt = 0;
start = System.currentTimeMillis();
for(int i=0; i<M; i++){
optArr = new int[max+1][n];
result = fastFun(max,n-1);
}
end = System.currentTimeMillis();
System.out.println("fastFun(max,n-1)):" + cnt);
System.out.println(result);
System.out.println("时间:" + (end-start));
cnt = 0;
start = System.currentTimeMillis();
for(int i=0; i<M; i++){
packOpt = new int[max+1];
pack01();
}
end = System.currentTimeMillis();
System.out.println(packOpt[max]);
System.out.println("循环次数:" + cnt);
System.out.println("时间:" + (end-start));
}
}
分享到:
相关推荐
动态规划 01背包问题 POJ3624可以AC
poj 算法题在poj.org上做的一些算法题poj.org 账号:xxfeixiang题目地址:例如,第1001题的地址为:
POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类
poj POJ是在线法官。 我想不到一个更好的名字。 它是用Python3和Django编写的。 它使用Docker和Celery进行提交评估。 Docker确保每个提交都在单独的容器中运行,而Celery使其全部异步。 我们在此处用于Celery的...
晒代码之二——多重背包(POJ1276)
POJ上的一道题目,自己写的代码,因为想下载别人的, 所以就放上了。
判定性背包问题 带附属关系的背包问题 <5> + -1背包问题 双背包求最优值 构造三角形问题 带上下界限制的背包问题(012背包) 3.线性的动态规划问题 积木游戏问题 <2>决斗(判定性问题) 圆的最大多边形问题 ...
北大POJ1004-Financial Management 解题报告+AC代码
leetcode oj 调试
poj 我在poj上的解题报告
放炮问题,北大网站 POJ 1185 算法
poj zhuli19901106在POJ上接受的问题的源代码。 自2010年起开始在POJ上进行编码〜
poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题...
NULL 博文链接:https://128kj.iteye.com/blog/1754756
POJ1321棋盘问题 很好两种解法很值得去参考一下 完整的实验报告还有代码希望kan
此仓库包含我对POJ( )上的ACM编程竞赛问题的解决方案。 您可以在上查看我在POJ上的个人资料。 问题使用其问题ID进行组织。 有关问题X的所有文件(例如1000、1001等)均以'X'命名,有关问题X的描述可在上找到。
POJ 这都是关于POJ上的ACM / ICPC程序的。
经典的0-1背包问题. 适合新手学习. 原题网址:http://poj.grids.cn/problem?id=2773
这是西北工业大学的POJ试题的答案,欢迎下载!
北大poj1012-Joseph【经典约瑟夫问题】 poj1012-Joseph【经典约瑟夫问题】