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;
}