| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 4639 | Accepted: 1290 |
Description
Input
Output
Sample Input
1 0 1 2 4 6 7
Sample Output
28
Source
/*
** Problem: POJ2718
** Status: Accepted
** Running Time: 16ms
** Author: Changmu
**
** 题意:给出最多10个单位数字,将这些数字分成两部分,求它们的
** 绝对值的最小值。
** 题解:开始总想着用搜索来枚举,,,后来才知道可以用贪心。具体的思路
** 是这样:如果N为2且有一个数为0时特判,如果N为偶数,那么找出最接近的
** 两个非零数,大的放到box1中,小的放在box2中,剩下的将最小的组合放到
** box1中,最大的组合放在box2,求出差值并更新ans;如果N为奇数,那么在
** 这N个数中,选择最小的一个非零数放到box1头边,然后剩下的数按照N为偶数的情况处理。
*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define maxn 12
#define inf 0x3f3f3f3f
int box[maxn], box1[maxn], box2[maxn], vis[maxn], num, num1, num2;
int minSub, ans, sign; // sign 用来标记奇偶
void Select(int k) {
for(int i = 0; k < num1 && i < num; ++i)
if(!vis[i]) {
vis[i] = 1;
box1[k++] = box[i];
}
for(int i = num - 1; sign < num2 && i >= 0; --i)
if(!vis[i]) {
box2[sign++] = box[i];
}
int a = 0, b = 0;
for(int i = 0; i < num1; ++i)
a = a * 10 + box1[i];
for(int i = 0; i < num2; ++i)
b = b * 10 + box2[i];
ans = std::min(ans, a - b);
}
int main() {
int T, i;
char ch;
scanf("%d", &T);
while(T--) {
num = 0;
while(scanf("%d%c", &box[num++], &ch)) {
vis[num-1] = 0;
if(ch == '\n') break;
}
std::sort(box, box + num);
num2 = num >> 1;
num1 = num - num2;
ans = inf;
if(num == 2 && box[0] == 0) { // 特判
printf("%d\n", box[1]);
continue;
}
minSub = 10;
sign = 0;
if(num & 1) {
if(box[0]) {
vis[0] = 1;
box1[0] = box[0];
} else {
vis[1] = 1;
box1[0] = box[1];
}
Select(1);
} else {
i = 1;
if(!box[0]) i = 2;
for( ; i < num; ++i)
minSub = std::min(minSub, box[i] - box[i-1]);
for(i = 1; i < num; ++i) {
if(box[i-1] && box[i] - box[i-1] == minSub) {
vis[i] = 1; vis[i-1] = 1;
box1[0] = box[i];
box2[0] = box[i-1];
sign = 1;
Select(1);
memset(vis, 0, sizeof(vis));
}
}
}
printf("%d\n", ans);
}
return 0;
}
POJ2718 Smallest Difference 【贪心+枚举】
原文:http://blog.csdn.net/chang_mu/article/details/40921753