题目链接http://poj.org/problem?id=1837
//思路:开一个G*(平衡度)的数组,DP找的就是状态,所以平衡度就是该状态~~表示DP真的不好~~继续DP吧!
//dp[i][j] 表示在挂满前i个物体的时,平衡度为j的挂法的数量。j为正表示右面重。
//最极端的情况是所有物体都挂在最远端,因此平衡度最大值为15*20*25=7500。原则上就应该有dp[ 0..20 ][-7500 .. 7500 ]。
//因此做一个处理,使得数组开为 dp[0.. 20][0..15000]。
//状态方程:dp[i][j]=sigma( dp[i-1][ j-c[k]*w[i] ] )
//memory 1396KB time 16ms
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdlib.h>
using namespace std;
int dp[21][15001];
int main()
{
int C,G,c[21],g[21];
while(scanf("%d%d",&C,&G)!=EOF)
{
for(int i=1;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][7500]=1;
for(int i=1;i<=G;i++)
for(int j=0;j<=15000;j++)
if(dp[i-1][j])
for(int k=1;k<=C;k++)
dp[i][j+g[i]*c[k]]+=dp[i-1][j];
printf("%d\n",dp[G][7500]);
}
return 0;
}
另外一种方法:
//POJ1837 DP balance
#include<cstdio>
#include<cstring>
int dp[15010],tp[15010];
int c[30];
int g[30];
int main ()
{
int C,G;
while(~scanf("%d%d",&C,&G))
{
memset(c,0,sizeof(c));
memset(g,0,sizeof(g));
for(int i=0;i<C;i++)//从1开始
{
scanf("%d",&c[i]);
}
for(int j=0;j<G;j++)
{
scanf("%d",&g[j]);
}
memset(dp,0,sizeof(dp)) ;
dp[7500]=1;//表示不用物体时,平衡度为0有一种挂法
for(int i=0;i<G;i++)
{
memcpy(tp,dp,sizeof(tp));
memset(dp,0,sizeof(dp));
for(int j=-7500;j<=7500;j++)
{
for(int k=0;k<C;k++)
{
dp[j+7500]+=tp[j+7500-g[i]*c[k]];
}
}
}
printf("%d\n",dp[7500]);
}
return 0;
}