现在的位置: 首页 > 综合 > 正文

poj 1837

2014年07月08日 ⁄ 综合 ⁄ 共 917字 ⁄ 字号 评论关闭

参照了 http://blog.sina.com.cn/s/blog_617615cd0100ewej.html

题目大意:给一个天平的悬挂点的坐标,和一些砝码,要你全部把砝码挂上去,保证天平平衡,一共有多少种方案

解题思路,动态规划,转换成0,1背包问题,用dp[i][j]表示前i个砝码都挂上,平衡度为j的方案数

dp[i][j + hooks[k] * weight[i]] += dp[i-1][j],hooks[k]表示第k个悬挂点的坐标,weight[i]表示第i个砝码的重量

由于平衡度会有负数的情况出现,所以我们要选取一个点作为0参考点,保证平衡度不会出现负数

选取力矩最小的绝对值作为0坐标参考点,即|hooks[i] * sum(weight[k])|,也就意味着0坐标点平移到这个坐标

最好dp[G][min]为所求,min = |hooks[i] * sum(weight[k])|

 

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int maxn = 15 * 20 * 25 + 1;

int dp[21][maxn], hooks[21], weight[21], C, G;
int main()
{
    int tot = 0;
    memset(dp, 0, sizeof(dp));
    scanf("%d %d", &C, &G);
    for(int i = 1; i <= C; i++)
        scanf("%d", &hooks[i]);
    for(int i = 1; i <= G; i++)
    {
        scanf("%d", &weight[i]);
        tot += weight[i];
    }
    int minv = tot * hooks[1], maxv = tot * hooks[C];
    int gap = maxv - minv;
    dp[0][-minv] = 1;
    for(int i = 1; i <= G; i++)
    {
        for(int j = 0; j <= gap; j++)
        {
            if(dp[i-1][j] > 0)
            {
                for(int k = 1; k <= C; k++)
                    dp[i][j+weight[i] * hooks[k]] += dp[i-1][j];
            }
        }
    }
    printf("%d\n", dp[G][-minv]);
    return 0;
}

 

抱歉!评论已关闭.