题目地址:Balance
题目大意:
有一个天平,天平左右两边各有若干个钩子,总共有C个钩子,有G个钩码,求将钩码全部挂到钩子上使天平平衡的方法的总数。中可以把天枰看做一个以x轴0点作为平衡点的横轴。
解题思路:
DP:最极端的平衡度是所有物体都挂在最远端,因此平衡度最大值为j=15*20*25=7500。原则上就应该有dp[ 1~20 ][-7500 ~ 7500 ]。 转化为01背包,其中 i 代表 前 i 个挂钩达到 j 平衡度的所有情况,因为是一个平衡所以求出中间值的平衡度情况就是所求的平衡的结果,因为存在负数dp转化为dp[ 1~20 ][0 ~ 16000]。 求出dp[G][8000]即可,记得初始化,初始化只能初始dp[0][8000],如果把所有挂钩为0的平衡度初始会影响结果。
可以设dp[i-1][j]=num,那么对于dp[i][j]来说有两种决策,就是选第i个砝码放在哪个位置或者不放。所以dp[i][j]+=dp[i-1][j-pos[k]*weight[i]]。当然前提条件是j>=pos[k]*weight[i].
代码:
1 #include <algorithm> 2 #include <iostream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cstdio> 7 #include <string> 8 #include <bitset> 9 #include <vector> 10 #include <queue> 11 #include <stack> 12 #include <cmath> 13 #include <list> 14 #include <map> 15 #include <set> 16 using namespace std;/***************************************/ 17 #define ll long long 18 #define int64 __int64/***************************************/ 19 const int INF = 0x7f7f7f7f; 20 const ll LINF = (1LL<<60); 21 const double eps = 1e-8; 22 const double PIE=acos(-1.0); 23 const int d1x[]= {0,-1,0,1}; 24 const int d1y[]= {-1,0,1,0}; 25 const int d2x[]= {0,-1,0,1}; 26 const int d2y[]= {1,0,-1,0}; 27 const int fx[]= {-1,-1,-1,0,0,1,1,1}; 28 const int fy[]= {-1,0,1,-1,1,-1,0,1}; 29 inline int min_32(int (a),int (b)){return (a)<(b)?(a):(b);} 30 inline int max_32(int (a),int (b)){return (a)>(b)?(a):(b);} 31 inline long long min_64(long long (a),long long (b)){return (a)<(b)?(a):(b);} 32 inline long long max_64(long long (a),long long (b)){return (a)>(b)?(a):(b);} 33 /***************************************/ 34 void openfile(){ 35 freopen("data.in","rb",stdin); 36 freopen("data.out","wb",stdout); 37 } 38 /**********************华丽丽的分割线,以上为模板部分*****************/ 39 40 int dp[21][20000];//代表第i个挂钩的平衡度的情况 41 int c[21]; 42 int g[21]; 43 int main() 44 { 45 int C,G; 46 while(scanf("%d%d",&C,&G)!=EOF) 47 { 48 memset(c,0,sizeof(c)); 49 memset(g,0,sizeof(g)); 50 memset(dp,0,sizeof(dp)); 51 int i,j,k; 52 for(i=1;i<=C;i++) 53 scanf("%d",&c[i]); 54 for(i=1;i<=G;i++) 55 scanf("%d",&g[i]); 56 // for(i=0;i<=16000;i++) 57 dp[0][8000]=1; //初始化 58 for(i=1;i<=G;i++) 59 for(j=0;j<=16000;j++) 60 for(k=1;k<=C;k++) 61 if (j>=c[k]*g[i]) 62 dp[i][j]+=dp[i-1][j-c[k]*g[i]]; 63 printf("%d ",dp[G][8000]); 64 } 65 return 0; 66 }