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

来源:互联网 发布:淘宝开店装修免费模板 编辑:程序博客网 时间:2024/06/05 16:25
超级书架
描述 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);//输出个数 //这里需要解释一下,由于在上面的循环中我是先检测是否大于书架高度的所以不需要减1return 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可以接受哈