USACO 2014 DEC Guard Mark 状态压缩

Problem 1: Guard Mark [Bill Cooperman, 2014]

Farmer John and his herd are playing frisbee.  Bessie throws the
frisbee down the field, but it's going straight to Mark the field hand
on the other team!  Mark has height H (1 <= H <= 1,000,000,000), but
there are N cows on Bessie's team gathered around Mark (2 <= N <= 20).
They can only catch the frisbee if they can stack up to be at least as
high as Mark.  Each of the N cows has a height, weight, and strength.
A cow's strength indicates the maximum amount of total weight of the
cows that can be stacked above her.  

Given these constraints, Bessie wants to know if it is possible for
her team to build a tall enough stack to catch the frisbee, and if so,
what is the maximum safety factor of such a stack.  The safety factor
of a stack is the amount of weight that can be added to the top of the
stack without exceeding any cow's strength.

INPUT: (file guard.in)

The first line of input contains N and H.

The next N lines of input each describe a cow, giving its height,
weight, and strength.  All are positive integers at most 1 billion.

SAMPLE INPUT:

4 10
9 4 1
3 3 5
5 5 10
4 4 5

OUTPUT: (file guard.out)

If Bessie's team can build a stack tall enough to catch the frisbee,
please output the maximum achievable safety factor for such a stack.
Otherwise output "Mark is too tall" (without the quotes).

SAMPLE OUTPUT:

2

 

分析

指向性非常的明显。数据量如果给出类似15或20这种数据,就一定想到“状态”这两个字。说白了,这道题就是枚举每一头牛到底要不要。

第18行的循环开始,以下都是枚举状态的。(1<<n - 1)就是最大状态,也就所有牛都取的情况。

关键的关键在于22行这个赋值语句。

max(f[i | 1<<(j-1)], min(f[i]-a[j].weight, a[j].strength))

第一个运算是里面的min取出来 去掉low那头奶牛的重量(如果把它压在下面,它不会承受自己的重量) 和 这头奶牛的体力的较小值,然后在和数组里原来的值取出更优的值。

接下来再计算高度是否可行,比较容易,不再细讲。最后判断是否是大于0的result,否则输出"Mark is too tall"。

 

卡点

卡了一个地方。

memset(f, -1, sizeof(f));

↑很重要……你想,他们有可能是0啊,也就是刚刚好撑住,最后一根稻草上去就塌了的情况……

 

程序

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,h;
 4 int f[2000000];
 5 struct cow
 6 {
 7     int height, weight, strength;
 8 }a[30];
 9 int main()
10 {
11     cin >> n >> h;
12     memset(f, -1, sizeof(f));
13     for(int i = 1; i <= n; i++)
14         cin >> a[i].height >> a[i].weight >> a[i].strength;
15     for(int i = 0; i <= n-1; i++)
16         f[1 << i] = a[i+1].strength;
17     int res = -1;
18     for (int i = 1; i<=((1<<n) -1); i++)
19     {
20         for(int j = 1; j <= n; j++)
21             if(!(i & 1<<(j-1)))
22                 f[i | 1<<(j-1)] = max(f[i | 1<<(j-1)], min(f[i]-a[j].weight, a[j].strength));
23         int sum_height = 0;
24         for (int j = 1; j <= n; j++)
25             if (i & 1 << (j-1))
26                 sum_height += a[j].height;
27         if (sum_height >= h)
28             res = max(res,f[i]);
29     }
30     if(res >= 0)
31         cout << res;
32     else
33         cout << "Mark is too tall";
34     return 0;
35 }

 

posted @ 2018-07-08 22:05  OptimusPrime_L  阅读(134)  评论(0编辑  收藏  举报