poj 1837-Balance

来源:互联网 发布:国学下载软件 编辑:程序博客网 时间:2024/05/05 12:14

http://poj.org/problem?id=1837

刚开始学习动态规划,以前只做过几道,比如最少零钱数问题啥的,这是个大坑,得好好练练。

此题看完一点也找不到思路。参考别人的代码写出来的,惭愧啊。

不过大牛们的代码都是把7500做为平衡点,个人认为没有必要,因为重量最大25,杠杆最长15,个数最多虽然是20个,但是为了保持平衡最多10个在一边,最关键一点,题目说了It is guaranteed that will exist at least one solution for each test case at the evaluation.即至少会有1个解,所以25×15×10=3750,这个数据做为平衡点就够了。

状态转化方程为dp[i+1][j+c[k]*g[i]] += dp[i][j],i代表层数,加一个砝码层数就多一层,j代表重量平衡的位置,因为数组不能有负数所以就有了上面的估计平衡点的大小。只要上一层的某一个重量的数组值非0就要根据方程状态转化。到最后只需要取你当初设置的平衡点的数组值就可以了。

理解完这题真的觉得DP不容易,看代码看的懂,自己想却想不出来,要好好加油了。

#include<cstdio>#include<ctype.h>#include<algorithm>#include<iostream>#include<string.h>using namespace std;int dp[21][7500+1];int main(){    int C,G,i,j,k;    int c[21],g[21];    cin>>C>>G;    for(i = 0; i < C; i++)        cin>>c[i];    for(i = 0; i < G; i++)        cin>>g[i];    memset(dp,0,sizeof(dp));    dp[0][3750] = 1;    for(i = 0; i < G; i++)        for(j = 0; j < 7500; j++)        {            if(dp[i][j] != 0)                for(k = 0; k < C; k++)                    dp[i+1][j+c[k]*g[i]] += dp[i][j];        }    cout<<dp[G][3750]<<endl;    return 0;}


0 0