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();
       }
}
原文地址:https://www.cnblogs.com/yzcstc/p/2977935.html