3900: 交换茸角
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 236 Solved: 104
[ Submit][ Status][ Discuss]
Description
动物园里有 n 头麋鹿。每头麋鹿有两支茸角,每支茸角有一个重量。然而,一旦某头麋鹿上
两支茸角的重量之差过大,这头麋鹿就会失去平衡摔倒。为了不然这种悲剧发生,动物园院长决
定交换某些茸角,使得任意一头麋鹿的两角重量差不超过 c。然而,交换两支茸角十分麻烦,不
仅因为茸角需要多个人来搬运,而且会给麋鹿造成痛苦。因此,你需要计算出最少交换次数,使
得任意一头麋鹿的两角重量差不超过 c。
注意,交换两支茸角只能在两头麋鹿之间进行。因为交换同一头麋鹿的两支角是没有意义的。
Input
第一行为整数 n,c。接下来 n 行,每行两个整数,分别表示一开始每头麋鹿的两角重量。
Output
一个数,即最少交换次数。如果无论如何也不能使每头麋鹿平衡,输出 -1。
Sample Input
3 0
3 3
2 5
2 5
3 3
2 5
2 5
Sample Output
1
HINT
对于 100% 的数据,n <= 16, c <= 1000000, 每支茸角重量不超过 1000000。
Source
首先看一下这个:http://blog.youkuaiyun.com/lvzelong2014/article/details/78897057
这题其实和bzoj2064方法基本一致。判断交换麋鹿可行性就是排个序然后相邻小于等于c即可。
然后对于一个合法状态最多只要交换n-1次,因为如果很傻地一个一个配对,前面配对n-1之后最后一对就配对完了。
然后就是和bzoj2064的状压一样了,只不过这题中单个1的状态可能是合法的,必须枚举子集。
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int read()
{
char ch = getchar(); int x = 0, f = 1;
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){x = x * 10 - '0' + ch; ch = getchar();}
return x * f;
}
int bin[20], a[20], b[20], h[40], f[100000], n, c, top;
int judge(int s) {
top = 0;
for(int i = 0;bin[i] <= s; ++i) if(bin[i] & s) h[++top] = a[i], h[++top] = b[i];
sort(h + 1, h + top + 1);
for(int i = 1;i < top; i += 2)
if(h[i + 1] - h[i] > c) return -1;
return 1;
}
int main() {
bin[0] = 1; for(int i = 1;i < 20; ++i) bin[i] = bin[i - 1] << 1;
n = read(); c = read();
for(int i = 0;i < n; ++i) a[i] = read(), b[i] = read();
if(!(~(f[bin[n] - 1] = judge(bin[n] - 1)))) {puts("-1"); return 0;}
for(int s = 1;s < bin[n] - 1; ++s) f[s] = judge(s);
for(int s = 1;s < bin[n]; ++s)
if(~f[s])
for(int t = (s - 1) & s; t; t = (t - 1) & s)
if(~f[t] && ~f[s ^ t])
f[s] = max(f[s], f[s ^ t] + f[t]);
printf("%d\n", n - f[bin[n] - 1]);
return 0;
}
本文介绍了一种通过交换麋鹿的茸角以确保其重量差不超过特定阈值的方法。通过状态压缩和动态规划实现了最小交换次数的有效计算。
598

被折叠的 条评论
为什么被折叠?



