标签:
题目链接:http://poj.org/problem?id=1837
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 10983 | Accepted: 6824 |
Description
Input
Output
Sample Input
2 4 -2 3 3 4 5 8
题目大意:有一个天平左右两边有C个挂钩,G个钩码。求将全部钩码都挂在钩子上是天平平衡的方法数。这个题目看过去真的是没想法,想想看考完六级,耐心的看完题意,但是能想到的只有用搜索,但是20^20的复杂度超时0.0
想了许久,用最简单的动态规划来写。动态规划的思想就是改变状态的时刻可以从前几状态的推出来。首先要先定义一个平衡度j,j=0表示天平平衡,j>0表示天平右偏,j<0表示天平向左倾。
其次,定义一个状态数组dp[i][j],表示挂满i个钩码的时候,平衡度为j时的挂法种数。那么每次挂上一个钩码后,对平衡状态的影响因素就是每个钩码的力臂
力臂=重量 *臂长 = w[i]*c[k];那么若在挂上第i个砝码之前,天枰的平衡度为j则挂上第i个钩码后,即把前i个钩码全部挂上天枰 后,天枰的平衡度 j=j+ w[i]*c[k]
特别注意:最极端的情况是所有物体都挂在最远端,因此平衡度最大值为15*20*25=7500。原则上就应该有dp[ 0..20 ][-7500 .. 7500 ]。因此做一个处理,使得数组开为 dp[0.. 20][0..15000]。
详见代码。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 using namespace std; 6 7 int dp[21][15100]; 8 9 int main() 10 { 11 int C,G; 12 int c[21],w[21]; 13 while (~scanf("%d%d",&C,&G)) 14 { 15 for (int i=1; i<=C; i++) 16 { 17 scanf("%d",&c[i]); 18 } 19 for (int j=1; j<=G; j++) 20 { 21 scanf ("%d",&w[j]); 22 } 23 memset(dp,0,sizeof(dp)); 24 dp[0][7500]=1; 25 for (int i=1; i<=G; i++) 26 for (int j=0; j<=15000; j++) 27 { 28 //cout<<1111<<endl; 29 for (int k=1; k<=C; k++) 30 dp[i][j+w[i]*c[k]]+=dp[i-1][j]; 31 } 32 printf ("%d\n",dp[G][7500]); 33 } 34 return 0; 35 }
标签:
原文地址:http://www.cnblogs.com/qq-star/p/4176990.html