题意:本题要求把一堆物品分成两堆,两堆总重量相差不到百分之2,即把物品进行背包,试着能否构成sum/(1 + 1.02)到sum/(1 + 1.02) * 1.02之间的一个数。
分析:背包搜索,当要从若干个物品中选出一些的时候,每次递归最好不要单纯地枚举第i个物品是要还是不要,而是要用一个循环从上一个要的物品开始去枚举下一个物品要第几个。
View Code
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
usingnamespace std;
#define maxn 105
double sum, rock[maxn];
bool vis[maxn];
int n;
void input()
{
sum =0;
for (int i =0; i < n; i++)
{
scanf("%lf", &rock[i]);
sum += rock[i];
}
}
bool dfs(double l, double r, int a)
{
for (int i = a; i < n; i++)
{
if (rock[i] >= l && rock[i] <= r)
{
vis[i] =true;
returntrue;
}elseif (rock[i] < l)
{
vis[i] =true;
if (dfs(l - rock[i], r - rock[i], i +1))
returntrue;
}
vis[i] =false;
}
returnfalse;
}
int main()
{
//freopen("t.txt", "r", stdin);
while (scanf("%d", &n), n)
{
input();
memset(vis, 0, sizeof(vis));
dfs(sum /2.02, sum *1.02/2.02, 0);
int i =0;
while (!vis[i])
i++;
printf("%d", i +1);
for (int j = i +1; j < n; j++)
if (vis[j])
printf(" %d", j +1);
putchar('\n');
}
return0;
}