poj 1837 Balance (DP)

来源:互联网 发布:南京淘宝招聘网 编辑:程序博客网 时间:2024/05/21 22:32

题目链接:http://poj.org/problem?id=1837

题意:给你一个天枰,再给你秤上一些挂钩的位置和秤砣,让你计算用这些钩子和秤砣使这个天枰平衡的方法数(秤砣必须全部使用)

题外话:这道是学长去年的Dp练习题,今天拿来做一下,刚开始的时候感觉这个题根本和Dp根本不占边呀(还是太弱了),之后去请教了一下隔壁寝室的大神,感觉豁然开朗。

思路:dp[i][j]表示用前i种秤砣,组成质量为j时的方法数,因为左边的挂钩是带重量的,而每个秤砣在天枰上产生的实际重量应该是 挂钩的位置*秤砣的质量 ,所以j就可能为负值,C++不支持带负数的数组,所以就把所有的权重+10000(大致计算了一下 这些秤砣产生的最大重量不可能超过一万),随意此时天秤的平衡状态就是j=10000的状态,最后输出dp[G][10000]。将dp数组初始化为零,将dp[0][10000]设成1(天枰本来就是平衡的)。    

Code:

#include <cmath>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <iostream>#include <queue>#include <vector>using namespace std;#define SIZE_M 25#define SIZE_N 20005#define INF 100000000int dp[SIZE_M][SIZE_N];int c[SIZE_M];int g[SIZE_M];int C,G;int main(){    scanf("%d%d",&C,&G);    for(int i=0;i<C;i++) scanf("%d",&c[i]);    for(int i=1;i<=G;i++) scanf("%d",&g[i]);    memset(dp,0,sizeof(dp));    dp[0][10000]=1;     for(int i=1;i<=G;i++){        for(int j=0;j<20000;j++){            if(dp[i-1][j]){                for(int k=0;k<C;k++) dp[i][j+g[i]*c[k]]+=dp[i-1][j];              }        }    }    printf("%d\n",dp[G][10000]);    return 0;}


总结: 这道题其实是背包问题很相似,在这两个问题中i都表示使用前i种物品,j都表示使用前i种物品所产生的一种属性,dp数组都是用来存最终结果,更新过程都是根据i-1的

所有j的值来更新所有i的j值,这其实是一种思维的方式,深悟,理解,体会~

0 0
原创粉丝点击