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 }
posted on 2018-08-13 11:43 Emiya_Kiritsugu 阅读(93) 评论(0) 编辑 收藏 举报