您的位置:首页 > 其它

POJ 3628 Bookshelf 2

2014-04-02 19:48 204 查看
题目大意:

FJ最近买了一座书架给奶牛图书馆,但是书架很快就被书填满了,现在只有顶上的一点空间可以放新书了,FJ现在有N头奶牛(1 ≤ N ≤ 20),每头牛的高度为[1, 1000000],而书架的高度为B(1 ≤ B ≤ S,S是所有牛高度的总和),为了达到书架的顶端牛可以叠罗汉,为了翻看顶端的书叠罗汉的高度不得小于B,但是叠的越高越危险,现在的任务就是求叠罗汉最少可以超过B多少。

现只有一个测例,测例中给出N和B,接下来会给出每头奶牛的高度,要求输出叠罗汉最少可以超过B多少。

题目链接

注释代码:

/*
* Problem ID : POJ 3628 Bookshelf 2
* Author     : Lirx.t.Una
* Language   : C
* Run Time   : 0 ms
* Run Memory : 320 KB
*/

#include <stdio.h>

//maximum exceeded height
//超出书架部分的最大长度
//20 × 1,000,000 - 1
#define	MAXXDH		19999999

//maximum number of cows
//奶牛的最大数量
#define	MAXCOWN		21

#define	MAX(x,y)	( (x) > (y) ? (x) : (y) )

//思路是先将所有奶牛高度相加再减去书架高度得到xd,表示最多可以超出多少高度
//再在这个xd中最多可以承受奶牛的高度dp
//xd - dp就是最小的超出书架的高度了
//因此可以讲xd看做背包,最终可以怎样往背包中放奶牛可以使得背包的价值最大(高度)
//而且的就是总价值(高度)减去这个最大价值(高度)

int		h[MAXCOWN];//height[i]表示第i头奶牛的高度,从下标1开始
//dp[i][j]表示i号奶牛放入高度为j的背包中所得的最大高度
//由01背包问题的结论得显然有dp[i][j] = MAX( dp[i - 1][j], dp[i - 1][ j - h[i] ] )
//前者表示i不放入背包,后者表示i放入背包
//因此可以看到数组dp[i]的值只与数组dp[i - 1]数组有关
//因此可以只用一个数组来表示滚动数组,将i这一维度给隐藏以减少空间
int		dp[MAXXDH];

int
main() {

int		n, b;//奶牛数量和书架高度
int		toth;//total height of cows,奶牛的总高度
int		xd;//exceeded height,所有奶牛高度超出书架的高度
int		i, j;//计数变量
int		tmp;//临时变量

scanf("%d%d", &n, &b);

for ( toth = 0, i = 1; i <= n; i++ ) {

scanf("%d", h + i);
toth += h[i];
}

for ( xd = toth - b, i = 1; i <= n; i++ )
//注意动态规划的方向是从后往前的,即从xd向h[i]方向动态规划的
//注意dp[i][x]是用dp[i - 1][x]更新的,更新完了以后就变成了dp[i][y]了
//具体讲,如果dp[2][3]已经用dp[1][2]更新了,等到dp[2][5]使用dp[1][3]更新时
//使用的其实是dp[2][3],因为这里使用的是一维滚动数组,把i维隐藏了,一旦先更新了
//前面的值,则后面的值更新时用的就不是上一维的了而是更新后的这一维的数据了
for ( j = xd; j >= h[i]; j-- ) {

tmp   = dp[ j - h[i] ] + h[i];//相当于dp[i - 1][ j - h[i] ]
dp[j] = MAX( dp[j], tmp );//相当于dp[i][j] = MAX( dp[i - 1][j], dp[i - 1][ j - h[i] ] )
}

printf("%d\n", xd - dp[xd]);

return 0;
}

无注释代码:

#include <stdio.h>

#define	MAXXDH		19999999

#define	MAXCOWN		21

#define	MAX(x,y)	( (x) > (y) ? (x) : (y) )

int		h[MAXCOWN];
int		dp[MAXXDH];

int
main() {

int		n, b;
int		toth;
int		xd;
int		i, j;
int		tmp;

scanf("%d%d", &n, &b);

for ( toth = 0, i = 1; i <= n; i++ ) {

scanf("%d", h + i);
toth += h[i];
}

for ( xd = toth - b, i = 1; i <= n; i++ )
for ( j = xd; j >= h[i]; j-- ) {

tmp   = dp[ j - h[i] ] + h[i];
dp[j] = MAX( dp[j], tmp );
}

printf("%d\n", xd - dp[xd]);

return 0;
}

单词解释:

bookshelf:n, 书架

fill up:vi, 填满

stack:n, 堆,垛堞
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: