POJ 1837:Balance 天平DP。。。
Balance
Time Limit: 1000MS
Memory Limit: 30000K
Total Submissions: 11878
Accepted: 7417
Description
Gigel has a strange balance and he wants to poise it. Actually, the device is different from any other ordinary balance.
It orders two arms of negligible weight and each arm's length is 15. Some hooks are attached to these arms and Gigel wants to hang up some weights from his collection of G weights (1 <= G <= 20) knowing that these weights have distinct values in the range 1..25. Gigel may droop any weight of any hook but he is forced to use all the weights.
Finally, Gigel managed to balance the device using the experience he gained at the National Olympiad in Informatics. Now he would like to know in how many ways the device can be balanced.
Knowing the repartition of the hooks and the set of the weights write a program that calculates the number of possibilities to balance the device.
It is guaranteed that will exist at least one solution for each test case at the evaluation.
Input
The input has the following structure:
• the first line contains the number C (2 <= C <= 20) and the number G (2 <= G <= 20);
• the next line contains C integer numbers (these numbers are also distinct and sorted in ascending order) in the range -15..15 representing the repartition of the hooks; each number represents the position relative to the center of the balance on the X axis (when no weights are attached the device is balanced and lined up to the X axis; the absolute value of the distances represents the distance between the hook and the balance center and the sign of the numbers determines the arm of the balance to which the hook is attached: '-' for the left arm and '+' for the right arm);
• on the next line there are G natural, distinct and sorted in ascending order numbers in the range 1..25 representing the weights' values.
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
題意是給了一個秤,然後給你幾個點的位置用來放秤砣,負號代表在秤的左邊,正好代表在秤的右邊。
然後又給了幾個秤砣,給了秤砣的重量。題目求的是用這些秤砣有多少種平衡方案。
讀完題根本沒感覺這是一道DP題。。。後來看得多了才發現應該看到這麼小的數值 就想到枚舉狀態,這樣逐漸往下推的DP,好歹這樣題也不少了,什麼分1 2 3 4 5 6石頭的,都是這種思想。
這題也是用DP[i][j]表示放置第i個秤砣 秤的狀態是j時的方案。
秤的狀態通過計算15*25*20,即最遠能到達7500。左右都是,即應該-7500到7500。但因為數組下標一定是大於等於零的,所以就用0~15000表示。
DP[0][7500]=1表示一個秤砣都沒放時,狀態在平衡狀態,且只有一種平衡方案。
然後就是。。。(我其實更願意把它說成是枚舉。。。)往下推。
核心代碼:
for(i=1;i<=G;i++)
{
for(j=0;j<=15000;j++)
{
for(k=1;k<=C;k++)
{
dp[i][j] += dp[i-1][j-weight[i]*weizhi[k]];
}
}
}
即對每一個給定的秤砣不斷枚舉其原來的狀態,不斷枚舉其所在位置,導致這次能達到的狀態。
代碼:
#include
#include
#include
#include
#include
#include
#pragma warning(disable:4996)
using namespace std;
//最大的狀態也就是所有的砝碼都放在了最端點的位置
//即20*25*15=7500 即-7500~7500
int dp[21][15001];
int weizhi[21];
int weight[21];
int main()
{
memset(dp,0,sizeof(dp));
dp[0][7500]=1;
int C,G,i,j,k;
cin>>C>>G;
for(i=1;i<=C;i++)
cin>>weizhi[i];
for(i=1;i<=G;i++)
cin>>weight[i];
for(i=1;i<=G;i++)
{
for(j=0;j<=15000;j++)
{
for(k=1;k<=C;k++)
{
dp[i][j] += dp[i-1][j-weight[i]*weizhi[k]];
}
}
}
cout<