题目描述
有一个天平,天平左右两边各有若干个钩子,总共有 C 个钩子,有 G 个钩
码,求将钩码全部挂到钩子上使天平平衡的方法的总数。
输入描述
第一行两个数 c, g 分别代表钩子数和钩码数
第二行 c 个数,表示每个钩子距离天平中央的距离 c[i],负数表示在左边,
正数表示在右边
第三行 g 个数,表示每个钩码的重量 w[i]
输出描述
输出总方案数
样例输入 2 4
-2 3
3 4 5 8
样例输出 2
数据范围及提
示
30%: c<=9, g<=9
100%: c<=20, g<=20, -15<=c[i]<=15, w[i]<=25
dp
【2017.10.10考试T3】
一道关于,,物理的DP,应用杠杆原理。
设计状态转移方程。定义j为平衡度。j>0时,往右偏;j<0时,往左偏。
dp[i][j]表示放上i个砝码时,平衡度为j时的方案数。
dp[i][j+w[i]*c[k]]=Σdp[i-1][j]
最终答案为:dp[g][7500]
平衡度范围:-7500~7500
由于数组不能访问负的下标,所以整体往右移7500。于是j的范围变为:0~15000
#include
#include
#include
using namespace std;
const int maxn=101;
int c[maxn],w[maxn],dp[25][15002];
int s,g;
int main()
{
scanf("%d%d",&s,&g);
for(int i=1;i<=s;i++)
scanf("%d",&c[i]);//每个钩子距天平的距离 s:钩子数量
for(int i=1;i<=g;i++)
scanf("%d",&w[i]);//g:钩码数量
memset(dp,0,sizeof(dp));//第一维:放置钩码的个数 第二维:平衡度
dp[0][7500]=1;//钩码数为0时,只有一种方案:不放
for(int i=1;i<=g;i++)//钩码
{
for(int j=0;j<=15000;j++)//平衡度
//if(dp[i-1][j])
for(int k=1;k<=s;k++)//钩子位置
dp[i][j+w[i]*c[k]]+=dp[i-1][j];
}
cout<7500]<<'\n';
return 0;
}
至于为什么要累加,wzhd说,dp[i][j]表示使用前i个钩码能够达到j平衡度的方案个数,所以要把所有符合条件的都加在一个数组中。
。。。
wzhd还说,a到b有4条路,c到b有5条路,那么a和b到c的总路径数还能等于4*5吗。。。
wzhd还给了另一种代码。。。
#include
#include
#include
#include
#include
using namespace std;
int c[25],w[25],dp[25][15000],n,m,ji[25][25];
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i ++) scanf("%d",&c[i]);
for(int i = 1;i <= m;i ++) scanf("%d",&w[i]);
for(int i = 1;i <= m;i ++)
for(int j = 1;j <= n;j ++)
ji[i][j] = w[i] * c[j];
dp[0][8000] = 1;
for(int i = 1;i <= m;i ++)
for(int j = 1;j <= n;j ++)
for(int k = 0;k <= 16000;k ++)
dp[i][k] += dp[i-1][k-ji[i][j]];
printf("%d",dp[m][8000]);
return 0;
}
wzhd终于把我讲明白了!!!
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
就是关于为什么是累加而不是累乘…..
在wzhd版代码中,假设dp[i][k]状态已定,又假设k只由k-5,k-6转移而来,再假设由之前的状态转移到k-5的方案数为2,转移到k-6的方案数为3,那么自然而然,转移到k的方案数有2+3=5种。
完。