POJ 1837 Balance

有一个 天平 ,天平 [-15,15] 区间上的整点有C个钩子 (2 <= C <= 20),有G个重量各不相同的砝码(2 <= G <= 20),重量为[1,25] ,现在把砝码全部挂在天平钩子上(一个钩子可以挂多个砝码也可不挂),现在问总共有多少种方案可以让挂上所有的砝码且保持天平平衡。

 

用动态规划的思想,dp[i][j]表示挂上 i 个砝码后倾斜度为j [-MID,MID] 的方案数,最终答案就是dp[G][0],

而最大的倾斜度MID = 15*(25+...+6),为了用数组我们不妨给j的范围加上MID,边界dp[0][MID]=1,其余为0,在用第 i+1 个砝码时,

if(dp[i][j]) dp[i+1][j+wei[i]*hook[k]]+=dp[i][j];//范围不会爆,但是代码里还是加了&&j+wei[i]*hook[k]>=0

dp[G][MID]为最终答案,用滚动数组。

 1 //#include <bits/stdc++.h>
 2 #include <vector>
 3 #include <cstdio>
 4 #include <iostream>
 5 #include <cstring>
 6 using namespace std;
 7 #define fst first
 8 #define scd second
 9 #define pb(x) push_back((x))
10 #define mkp(x,y) make_pair((x),(y)) 
11 #define ist(x) insert((x))
12 typedef long long ll;
13 typedef pair<int ,int > pii;
14 typedef pair<ll ,ll > pll;
15 typedef vector< int > vi;
16 ll gcd(ll a,ll b){ return b==0?a:gcd(b,a%b);}
17 ll qPow(ll a,ll b,ll mod){ ll ret=1ll;while(b){ if(b&1) ret=ret*a%mod;a=a*a%mod;b>>=1;} return ret; }
18 
19 const int MID=4650;
20 int dp[2][2*MID+10];
21 
22 int main(){
23     int C,G;
24     cin>>C>>G;
25     vi hook(C),wei(G);
26     for(int i=0;i<C;++i) cin>>hook[i];
27     for(int i=0;i<G;++i) cin>>wei[i];
28     memset(dp,0,sizeof(dp));
29     int now=0;
30     dp[now][MID]=1;
31     for(int i=0;i<G;++i){
32         memset(dp[now^1],0,sizeof(dp[now^1]));
33         for(int j=0;j<=2*MID;++j){
34             for(int k=0;k<C;++k){
35                 if(dp[now][j]&&j+wei[i]*hook[k]>=0)
36                     dp[now^1][j+wei[i]*hook[k]]+=dp[now][j];
37             }
38         }
39         now^=1;
40     }
41     cout<<dp[now][MID]<<endl;
42     return 0;
43 }
View Code

 

posted on 2018-08-13 11:43  Emiya_Kiritsugu  阅读(93)  评论(0编辑  收藏  举报

导航