好长时间没写解题报告了,这次来两道水题:超级书架1099 和 超级书架2 1100 TYVJ

超级书架

描述 Description
     Farmer John最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此的大,但它还是几乎瞬间就被各种各样的书塞满了。现在,只有书架的顶上还留有一点空间。

     所有N(1 <= N <= 20,000)头奶牛都有一个确定的身高H_i(1 <= H_i <= 10,000)。设所有奶牛身高的和为S。书架的高度为B,并且保证1 <= B <= S < 2,000,000,007。
     为了够到比最高的那头奶牛还要高的书架顶,奶牛们不得不象演杂技一般,一头站在另一头的背上,叠成一座“奶牛塔”。当然,这个塔的高度,就是塔中所有奶牛的身高之和。为了往书架顶上放东西,所有奶牛的身高和必须不小于书架的高度。显然,塔中的奶牛数目越多,整座塔就越不稳定,于是奶牛们希望在能够到书架顶的前提下,让塔中奶牛的数目尽量少。
     现在,奶牛们找到了你,希望你帮她们计算这个最小的数目。


输入格式 Input Format


第1行: 2个用空格隔开的整数:N 和 B
第2..N+1行: 第i+1行是1个整数:H_i


输出格式 Output Format


第1行: 输出1个整数,即最少要多少头奶牛叠成塔,才能够到书架顶部


样例输入 Sample Input
6 40
6
18
11
13
19
11

样例输出 Sample Output
3

时间限制 Time Limitation
各个测试点1s


注释 Hint
输入说明:
一共有6头奶牛,书架的高度为40,奶牛们的身高在6..19之间。
输出说明:
一种只用3头奶牛就达到高度40的方法:18+11+13。当然还有其他方法,在此不一一列出了。



解题思路 solution:
直接降序(从大到小)快排
再一个个累加直到比书架高就停,再输出个数



C代码:

#include <stdio.h>

int a[200000];//奶牛的高度都在这里 

int n,b; //总数n和书架的高度b 

//标准的快排,不多解释
void qsort(int x, int y) 
{
	int i,j,m,t;
	m = a[(x+y)/2];
	i = x; j = y;
	do {
		while(a[i] > m) i++;
		while(a[j] < m) j--;
		if(i<=j) {
			t = a[i]; a[i] = a[j]; a[j] = t;
			i++;j--;
		}
	} while (i<=j);
	if(i < y) qsort(i,y);
	if(x < j) qsort(x,j);
}

int main()
{
	int i,sum = 0;//i是循环变量
	//freopen("1099.in","r",stdin);
	//freopen("1099.out","w",stdout);这两句测试用的
	
	scanf("%d%d",&n,&b);
	
	for(i=0;i<n;i++) {
		scanf("%d",&a[i]);
	}
	
	qsort(0,n-1);//从大到小排序
	
	for(i=0;i<n;i++) {
		if(sum >= b) break;//只要加到大于书架高度就退出循环
		sum += a[i];//逐个累加
	}
	
	printf("%d\n",i);//输出个数 
//这里需要解释一下,由于在上面的循环中我是先检测是否大于书架高度的所以不需要减1
	
	return 0;
}



总结:由于我是先做的超级书架2,再做这题的,一开始想到dp上去了,搞复杂了……后来才想到直接快排就解决了。


超级书架2
描述 Description
     Farmer John最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此的大,但它还是几乎瞬间就被各种各样的书塞满了。现在,只有书架的顶上还留有一点空间。
     所有N(1 <= N <= 20)头奶牛都有一个确定的身高H_i(1 <= H_i <= 1,000,000 – 好高的奶牛>_<)。设所有奶牛身高的和为S。书架的高度为B,并且保证1 <= B <= S。
     为了够到比最高的那头奶牛还要高的书架顶,奶牛们不得不象演杂技一般,一头站在另一头的背上,叠成一座“奶牛塔”。当然,这个塔的高度,就是塔中所有奶牛的身高之和。为了往书架顶上放东西,所有奶牛的身高和必须不小于书架的高度。
     塔叠得越高便越不稳定,于是奶牛们希望找到一种方案,使得叠出的塔在高度不小于书架高度的情况下,高度尽可能小。你也可以猜到你的任务了:写一个程序,计算奶牛们叠成的塔在满足要求的情况下,最少要比书架高多少。


输入格式 Input Format
第1行: 2个用空格隔开的整数:N 和 B
第2..N+1行: 第i+1行是1个整数:H_i


输出格式 Output Format
第1行: 输出1个非负整数,即奶牛们叠成的塔最少比书架高的高度


样例输入 Sample Input
5 16
3
1
3
5
6

样例输出 Sample Output
1

时间限制 Time Limitation 
各个测试点1s
注释 Hint 

我们选用奶牛1、3、4、5叠成塔,她们的总高度为3 + 3 + 5 + 6 = 17。任何方案都无法叠出高度为16的塔,于是答案为1。



解题思路 solution:
0\1揹包变种
布尔型动态规划
算出所有奶牛的身高和记为sum
f[n]表示n高度能否达到 非0为能 0为不能
核心代码

f[0] = 1; 0高度当然能到达了
for (i=0;i<n;i++) {
     for (j=sum;j>=a[i];j–) {揹包 揹包 还是揹包
          if(f[j-a[i]]) f[j] = f[j-a[i]];
     }
}

if(f[j-a[i]]) f[j] = f[j-a[i]];如果j-a[i]可以达到 则 f[j]也可以达到



C代码:

#include <stdio.h>

int n,b;//跟上题一样 我们可爱的nb大叔
int a[100];//奶牛的高度(数组往大了开,如果是要挑战极限的话就要节省一下空间)
int f[21000000]; //f[n]的含义在上面已经说清楚了

int main()
{
	int i,j,sum=0;
	//freopen("1100.in","r",stdin);
	//freopen("1100.out","w",stdout);
	
	scanf("%d%d",&n,&b);
	
	for (i=0;i<n;i++) {
		scanf("%d",&a[i]);
		sum += a[i];//总和
	}
	f[0] = 1;
	for (i=0;i<n;i++) {
		for (j=sum;j>=a[i];j--) {
			if(f[j-a[i]]) f[j] = f[j-a[i]];
		}
	}
	
	for (i=b;i<=sum;i++) {//注意是从哪里开始到哪里结束的
		if(f[i])break;//找到最先的就退出
	}
	
	printf("%d\n",i-b);//高出的高度
	
	return 0;
}



总结:动态规划,0/1揹包,装箱问题…….
因为这里的n最大只有20所以有的解法是直接枚举,那样也可以因为所有的情况只有2的20次方等于1048576可以接受哈

点赞