您的位置:首页 > Web前端

usaco 4.1 Fence Rails 剪枝

2008-08-21 13:27 363 查看
多维背包问题,不能用dp,因为n <= 50,所以剪枝搜索可以处理,对于每个rail,枚举它是从哪个board截取的,从一下几个方面剪枝即可

1)对rail和board排序,对于不同长度的rail,一定是取长度小的rail比较划算,所以我们取前k个rail处理
这里 sum(rail,k) <= sum(board) 并且 sum(rail,k+1) > sum(board)

2)充分利用题目条件:因为每个rail最长只有128,而rail可能会有1000,所以肯定有很多rail的长度相等,对于这些rail,我们只需要枚举一个下界即可,这样可以免

去很多重复的搜索

3)按照答案的要求搜索:按照rail的个数从多到少搜索,则第一次搜索到结果即可输出

4)设board之和是sum_board,n个rail之和sum_rail, 则最多只能浪费 sum_board - sum_rail 这么多木材,因为如果浪费更多的话,则剩余board肯定不够切

#include <iostream>

#include <algorithm>

using namespace std;

/*

PROG: fence8

LANG: C++

ID: heben991

*/

const int B = 60, R = 1100, L = 130;

int board[B], rail[R], nboard, nrail;

int remain[B], from[R], f[R], lim[R], board_sum, rail_sum;

int ans, waste_max;

void dfs(int k, int waste)

{

if(k < 0)

{

printf("%d/n", ans+1);

exit(0);

}

int i;

if(k != ans && rail[k] == rail[k+1]) i = from[k+1];

else i = 0;

for(; i < nboard; ++i)

if(remain[i] >= rail[k])

{

from[k] = i;

remain[i] -= rail[k];

if(remain[i] < rail[0]) waste += remain[i];

if(waste > waste_max)

{

waste -= remain[i]; //hint

remain[i] += rail[k];

continue;

}

dfs(k-1,waste);

remain[i] += rail[k];

}

}

int main()

{

int i, j, k, t;

freopen("fence8.in", "r", stdin);

freopen("fence8.out","w",stdout);

scanf("%d", &nboard);

board_sum = 0;

for(i = 0; i < nboard; ++i)

{

scanf("%d", board+i);

board_sum += board[i];

}

sort(board,board+nboard);

for(i = 0; i < nboard; ++i) remain[i] = board[i];

scanf("%d", &nrail);

for(i = 0; i < nrail; ++i)

{

scanf("%d", rail+i);

}

sort(rail,rail+nrail);

for(i = 0; i < nrail; ++i)

{

if(rail_sum + rail[i] > board_sum) break;

rail_sum += rail[i];

}

nrail = i;

for(i = nrail-1; i >= 0; --i)

{

ans = i;

waste_max = board_sum - rail_sum;

rail_sum -= rail[i];

dfs(i,0);

}

puts("0");

return 0;

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