poj1853
题意:给一堆物品分成两堆,两堆总重量相差不到百分之2。。。
思路:本题是个好题。。很新颖的dp。。
因为n与给定的数字都不超过100,且允许误差为2%,所以我们可以进行放大,把小数化成整数,这样就可以进行dp了。。具体是把所有总数看成20000粉,然后按比率分配。。分配为进行背包。。
/* State:Accepted Time:2013-03-12 00:12:37 */ #include <iostream> #include <cstring> #include <string> #include <cstdlib> #include <cstdio> #include <algorithm> #include <cmath> #include <queue> using namespace std; struct oo{ int l, p , s; }; int n , f[20010], g[20100], a[120],tm; float sum(0); void init() { float b[120]; sum = 0; memset(g,0,sizeof(g)); memset(f,0,sizeof(f)); memset(a,0,sizeof(a)); for (int i = 1; i <= n; ++i) { scanf("%f", &b[i]); sum += b[i]; } for (int i = 1; i <= n; ++i) a[i] = b[i]/sum * 20000; } void print(int now) { if (now == 0) return; int i = g[now]; print(now - a[i]); printf("%d ",i); } void dp() { f[0] = 1; for (int i = 1; i <=n; ++i) for (int j = 10000; j >=0; --j) if (f[j] && !f[j + a[i]]) { f[j + a[i]] = 1; g[j + a[i]] = i; } int i; for (i = 10000; i >= 0; --i) if (f[i]) break; print(i); printf("\n"); } int main(){ freopen("poj1853.in","r",stdin); freopen("poj1853.out","w",stdout); while (scanf("%d",&n)!=EOF && n) { init(); dp(); } }