题意挺简单,思路也不难,但是开始一直WA。
这里的技巧就是:把所有数据扩大根号 2 倍,化根号为整数,避免精度损失(用 double 各种 WA,不知道是用怎样的数据卡的。。。)
另外发现一点:sqrt(2) 会报CE,必须写成 sqrt(2.0)
刚开始自己加了个“优化”,WA了好几发,然后找到了反例。。注释掉了。。。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn = 55;
const int inf = 1e9;
int side[maxn], rad[maxn], pos[maxn];
bool cover[maxn];
int main()
{
int n;
while(~scanf("%d", &n) && n) {
memset(cover, false, sizeof(cover));
scanf("%d", &side[0]);
rad[0] = pos[0] = side[0];
for(int i = 1; i < n; i++) {
int curmin = inf;
scanf("%d", &side[i]);
rad[i] = side[i];
for(int j = 0; j < i; j++) {
// if(!cover[j]) {
bool cross = false;
int temp = pos[j] + 2 * min(rad[i], rad[j]);
for(int k = 0; k < i; k++) {
if(k == j) continue;
if(temp - pos[k] < 2 * min(rad[i], rad[k])) {
cross = true;
break;
}
}
if(!cross)
curmin = min(curmin, pos[j] + 2 * min(rad[i], rad[j]));
// }
}
pos[i] = curmin;
// for(int j = 0; j < i; j++) {
// if(!cover[j] && pos[i] > pos[j] + rad[j])
// cover[j] = true;
// }
}
bool first = true;
for(int i = 0; i < n; i++) {
bool vis = true;
int lf = pos[i] - rad[i], rt = pos[i] + rad[i];
for(int j = 0; j < n; j++) {
if(j == i || rad[j] <= rad[i]) continue;
if(pos[j] - rad[j] <= lf)
lf = max(lf, pos[j] + rad[j]);
if(pos[j] + rad[j] >= rt)
rt = min(rt, pos[j] - rad[j]);
if(lf >= rt) {
vis = false;
break;
}
}
if(vis) {
if(first) {
printf("%d", i+1);
first = false;
} else
printf(" %d", i+1);
}
}
printf("\n");
}
return 0;
}