3900: 交换茸角
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 165 Solved: 72
[ 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
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#include<cmath>
#include<stack>
#define min(a,b) ((a) < (b) ? (a) : (b))
using namespace std;
const int N = 16;
const int M = (1 << N);
int n,c,a[N],b[N],d[233],f[M];
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
cin >> n >> c;
for (int i = 0; i < n; i++) scanf("%d%d",&a[i],&b[i]);
for (int o = 1; o < (1 << n); o++)
{
int tp = 0;
for (int x = o,now = 0; x; x >>= 1,now++)
if (x & 1) d[++tp] = a[now],d[++tp] = b[now];
bool pass = 1; sort(d + 1,d + tp + 1);
for (int i = 1; i < tp; i += 2)
if (d[i + 1] - d[i] > c) pass = 0;
f[o] = pass ? (tp / 2 - 1) : M;
for (int op = o - 1 & o; op; op = op - 1 & o)
f[o] = min(f[o],f[op] + f[o ^ op]);
}
cout << (f[(1 << n) - 1] == M ? -1 : f[(1 << n) - 1]) << endl;
return 0;
}