动态规划dp——天平2
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5616
Jam's balance
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2359 Accepted Submission(s): 964
Problem Description
Jim has a balance and N weights. (1≤N≤20)
The balance can only tell whether things on different side are the same weight.
Weights can be put on left side or right side arbitrarily.
Please tell whether the balance can measure an object of weight M.
The balance can only tell whether things on different side are the same weight.
Weights can be put on left side or right side arbitrarily.
Please tell whether the balance can measure an object of weight M.
Input
The first line is a integer T(1≤T≤5)
, means T test cases.
For each test case :
The first line is N , means the number of weights.
The second line are N number, i'th number wi(1≤wi≤100) means the i'th weight's weight is wi .
The third line is a number M . M is the weight of the object being measured.
For each test case :
The first line is N , means the number of weights.
The second line are N number, i'th number wi(1≤wi≤100) means the i'th weight's weight is wi .
The third line is a number M . M is the weight of the object being measured.
Output
You should output the "YES"or"NO".
Sample Input
1
2
1 4
3
2
4
5
Sample Output
NO YES YES
Hint
For the Case 1:Put the 4 weight alone For the Case 2:Put the 4 weight and 1 weight on both side题解: 又是一道天平问题,本题类似于;排列组合,可以用母函数做!
ok!
首先我们定义一个数组 dp[ i ][ j]:表示用前i个砝码中的部分或全部,是否可以使得天平右边比左边重j克,或者左边比右边重 j 克;
dp[i][j]==1 表示存在一种挂法 用前i个砝码挂在天平的 使得天平右边比左边重j克(或左边比右边重 j 克)
dp[i][j]==0 表示不存在。
其次 weight[ i ]:表示第i个砝码的重量。
( emmm,动态规划总是这样,dp数组的值一般对应问题的解,要想明白下标的含义及其关系)
分析啦::
如果 不使用的i个砝码:则 d[i ][ j ] = d[i-1 ][ j ];
如果 使用第i个砝码: 则 d[ i ][ j ]=max{ d[i-1][ (int) abs( j- weight[i] ) ] , d[i-1][ j+weight[i] ] }
因为d[i][j] :如果使用第i个砝码,那么要使得天平右边比左边重j克( 或左边比右边重 j 克 ), 只有用前 i-1 个砝码,使得天平左偏 j + weight[i] 克,这时天
平右边边放第i个砝码,即天平左偏j 克,d[ i ][ j ] = d[i-1][ j+weight[i] ] ,其他情况同理。
代码实现:
#include<iostream> #include<cstring> #include<cmath> using namespace std; int dp[25][2500]; int main(){ int t; cin>>t; while(t--){ int n; cin>>n; memset(dp,0,sizeof(dp)); int a; cin>>a; dp[1][a]=dp[1][0]=1; for(int i=2;i<=n;i++){ cin>>a; dp[i][0]=1; for(int j=0;j<=2100;j++){ dp[i][j]=dp[i-1][j]; if(!dp[i][j]) { dp[i][j]=max(dp[i-1][(int)abs(j-a) ],dp[i-1][j+a]); } } } int x; cin>>x; while(x--){ cin>>a; if(dp[n][a]) cout<<"YES"<<endl; else cout<<"NO"<<endl; } } }