Description
Gigel has a strange "balance" and he wants to poise it. Actually, the device is different from any other ordinary balance.Input
The input has the following structure:Output
The output contains the number M representing the number of possibilities to poise the balance.Sample Input
2 4 -2 3 3 4 5 8
Sample Output
2
題意:一個天平上有C個掛鉤,第i個掛鉤的位置為C[i],C[i] < 0表示該掛鉤在原點的左邊,C[i] > 0表示該掛鉤在原點的右邊;然後給出G個鉤碼的重量,問有多少種掛法使得天平保持平衡。
分析:當天平平衡時,每向天平上掛一個鉤碼,天平的狀態就會改變,而這個狀態可以由若干前一狀態獲得。
首先定義一個平衡度j的概念
當平衡度j=0時,說明天枰達到平衡,j>0,說明天枰傾向右邊(x軸右半軸),j<0則相反
那麼此時可以把平衡度j看做衡量當前天枰狀態的一個值
因此可以定義一個 狀態數組dp[i][j],意為在掛滿前i個鉤碼時,平衡度為j的掛法的數量。
由於距離L[i]的范圍是-15~15,鉤碼重量的范圍是w[i]是1~25,鉤碼數量最大是20
因此最極端的平衡度是所有物體都掛在最遠端,因此平衡度最大值為j=15*20*25=7500。原則上就應該有dp[ 1~20 ][-7500 ~ 7500 ]。
因此為了不讓下標出現負數,做一個處理,使得數組開為 dp[1~20][0~15000],令7500對應0,則當j=7500時天枰為平衡狀態。
/*
dp[i][j]表示用了前i個鉤碼,天平兩端的差值(右端 - 左端)為j時的方案數。
極端情況為所有鉤碼全部掛在左端的最左邊位置,根據題目數據可知此時差值最大為
0 - 15 * 25 * 20 = -7500,所以要加上一個偏移量,用7500對應0,假設鉤碼數量為G,
則最終答案為dp[G][7500]。
轉移方程:dp[i][j + w[i] * l[k]] = Sigma(dp[i-1][j])。
k為第k個掛鉤位置
*/
#include
#include
#include
using namespace std;
int dp[21][15005];
int l[21], w[21];
int main() {
int C, G;
while(~scanf("%d%d", &C, &G)) {
for(int i = 1; i <= C; i++)
scanf("%d", &l[i]);
for(int i = 1; i <= G; i++)
scanf("%d", &w[i]);
memset(dp, 0, sizeof(dp)); //達到每個狀態的方法數初始化為0
dp[0][7500] = 1; // 0對應7500,掛上前0個鉤碼後,天枰達到平衡狀態7500的方法有1個,就是兩端都不掛
for(int i = 1; i <= G; i++) {
for(int j = 0; j <= 15000; j++) {
if(dp[i-1][j]) { // 當放入i-1個鉤碼時狀態j已經出現且被統計過方法數,則直接使用統計結果,否則忽略當前狀態j
for(int k = 1; k <= C; k++) {
dp[i][j + w[i] * l[k]] += dp[i - 1][j];
}
}
}
}
printf("%d\n", dp[G][7500]);
}
return 0;
}