• 动态规划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. (1N20)
    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(1T5) , 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(1wi100) 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;
    		}
    	
    	}
    }
    

      

  • 相关阅读:
    ASP.NET网页动态添加数据行
    动态生成自定义控件ascx如何给ascx传值
    读取txt文件将文本行组合成特定格式
    怎样对文本文件内的文本行排序
    动态变更Repeater控件HeaderTemplate列名
    减少代码冗余,封装你的程序
    在Repeater控件的OnItemDataBound获取数据源记录总数
    查看服务器系统资源(cpu,内容)利用率前几位的进程的方法
    Nginx反向代理+缓存开启+url重写+负载均衡(带健康探测)的部署记录
    gerrit代码简单备份方案分享
  • 原文地址:https://www.cnblogs.com/z-bear/p/9473484.html
Copyright © 2020-2023  润新知