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;
}
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;
}
相关文章推荐
- USACO 4.1 Fence rails(迭代加深DFS+二分)
- usaco 4.1.2 Fence Rails 搜索剪枝
- USACO 4.1 Fence Rails
- USACO 4.1 Fence Rails (fence8)
- usaco 4.1 Fence Rails
- Section 4.1 Fence Rails(DFS_ID迭代加深搜索+剪枝)
- USACO Section 4.1 Fence Rails
- USACO Section 4.1 Cryptcowgraphy - BT的DFS剪枝..
- USACO 6.3 Fence Rails(一道纯剪枝应用)
- usaco 4.1 Cryptcowgraphy 剪枝
- USACO Section 4.1 Fence Rails(DFSID)
- USACO 4.1 Fence Rails
- [USACO]Fence Rails
- USACO 4.1 Beef McNuggets
- [USACO 6.3.1] Fence Rails
- USACO 4.1 Cryptcowgraphy dfs+剪枝
- USACO6.1 动态规划_剪枝_01二叉树
- USACO Section 4.1 Beef McNuggets - 描述真吓人~
- 【USACO4.1.2】栅栏的木料 爆搜剪枝优化
- usaco 1.3 Prime Cryptarithm(简单哈希表暴搜剪枝)