POJ1837 分组背包 xingxing在努力

  题目的意思是有一个天平两臂各挂一些钩子, 每个钩子下面可以挂一些砝码, 问在使用所有的砝码的情况下有多少种方法可以使天平平衡?该问题可以转化成分组背包的问题,大体如下对于每一种砝码来说我们可以关在任意一个钩子下面,这些事件是互斥的,一个砝码一个组进行分组背包即可,注意的是有负的力矩的存在, 因此我们将坐标轴移动到10000即可,代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
int C, G;
int pos[25];
int weight[25];
int M = 10000;
int f[25][20000];

int main()
{
    while(scanf("%d%d", &C, &G) == 2)
    {
        for(int i=1; i<=C; i++)
            scanf("%d", &pos[i]);
        for(int i=1; i<=G; i++)
            scanf("%d", &weight[i]);
        memset(f, 0, sizeof(f));
        f[0][M] = 1;
        for(int i=1; i<=G; i++)
            for(int j=0; j<=20000; j++)     //有人说这个必须正向循环,其实没必要的。。也可以负向
            {
                for(int k=1; k<=C; k++)      //第i个砝码挂到第k个位置上
                {
                    int tp = weight[i]*pos[k];
                    if(j-tp>=0 && j-tp<=20000 && f[i-1][j-tp])
                        f[i][j] += f[i-1][j-tp];
                }
            }
        printf("%d\n", f[G][M]);
    }
    return 0;
}

 

 

使用了优化内存的方法:

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
int C, G;
int pos[25];
int weight[25];
int M = 10000;
int f[2][20000];

int main()
{
    while(scanf("%d%d", &C, &G) == 2)
    {
        for(int i=1; i<=C; i++)
            scanf("%d", &pos[i]);
        for(int i=1; i<=G; i++)
            scanf("%d", &weight[i]);
        memset(f, 0, sizeof(f));
        f[0][M] = 1;
        for(int i=1; i<=G; i++)
        {
            memset(f[i%2], 0, sizeof(f[i%2]));
            for(int j=0; j<=20000; j++)
            {
                for(int k=1; k<=C; k++)      //第i个砝码挂到第k个位置上
                {
                    int tp = weight[i]*pos[k];
                    if(j-tp>=0 && j-tp<=20000 && f[(i-1)%2][j-tp])
                        f[i%2][j] += f[(i-1)%2][j-tp];
                }
            }
        }
        printf("%d\n", f[G%2][M]);
    }
    return 0;
}

 

posted @ 2015-12-03 14:39  xing-xing  阅读(178)  评论(0编辑  收藏  举报