zoukankan      html  css  js  c++  java
  • 湖南多校对抗赛---Rectangle(01背包)

     题目网址:http://acm.csu.edu.cn/OnlineJudge/problem.php?cid=2071&pid=0

    Description

    Now ,there are some rectangles. The area of these rectangles is 1* x or 2 * x ,and now you need find a big enough rectangle( 2 * m) so that you can put all rectangles into it(these rectangles can't rotate). please calculate the minimum m satisfy the condition.

    Input

    There are some tests ,the first line give you the test number.
    Each test will give you a number n (1<=n<=100)show the rectangles number .The following n rows , each row will give you tow number a and b. (a = 1 or 2 , 1<=b<=100).

    Output

    Each test you will output the minimum number m to fill all these rectangles.

    Sample Input

    2
    3
    1 2
    2 2
    2 3
    3
    1 2
    1 2
    1 3

    Sample Output

    7
    4
     

    解题Report:

    显然题意很简单,就是找出能盛下所有矩形的最小的大矩形(注意条件小矩形的宽为1或2,大矩形的宽为2),另外不能够旋转(开始的时候题意根本没有说清楚,以为小的不能旋转,但是大的能够旋转,吃了很大的亏,因为这样的话1,2    2,2     2,2这样的测试数据需要把前面的数相加,也就是应该是5,但是事实证明这样时候是想多了)

    其实刚拿到题的时候就把这道题归为了01背包的问题,就是小矩形的宽为2的直接相加,剩下的为1的就放在背包里就行了,也就是说从宽度小于1的和的一半(注意奇偶性)开始遍历,每次把背包的容量加1,当背包正好装满的时候这就是最小的长度,所以很简单喽

    开始的时候一直没有A掉,就是因为没有初始化,第一次背包没有装满,当第二次的时候就直接用上一次的那个数组了,这样肯定是不对的,然后想了好多的边界条件,结果是越改越错,越改越不对了,这个可恨的错还是比赛之后查出来的,当时A的用的是第二种大哭大哭大哭。。。


    代码:

     #include <iostream>
    #include <string.h>
    #include <stdio.h>
    using namespace std;
    int main()
    {
    int T;
    cin>>T;
    while(T--)
    {
    	int n,count=0,tmp=0,vol[1001],f[10050]={0},sum=0;
    	int a,b;
    	cin>>n;
        while(n--){
        	cin>>a>>b;
        	if(a==2) count+=b;
        	else {
    		  vol[tmp++]=b;
    		  sum+=b;
        	}
        } 
        int xx=(sum%2==0?sum/2:sum/2+1);
    	for(int v=xx;v<=sum;v++){
    		memset(f,0,sizeof(f));
    		for(int i = 0 ; i < tmp ; i++)  //便利i件物品
            {
                for(int j = v ; j >= vol[i]; j--)
                {
                    int tem = f[  j-vol[i]  ] + vol[i];
                    if( f[j] < tem )
                    f[j] = tem;
                }
            }
            if(f[v]==v) 
    		{
            cout<<count+v;
    		if(T!=0) cout<<endl;
            break;
    		}
    	} 
    }
     return 0;
    }
    

    没有办法,受人启发,WR了好几次只好稍微改了下思路,但是动规的思路没有改,也就是在看背包的时候直接用和的一半做背包的容积,运用01背包的方式,找出能盛下的最大的体积,然后和剩下的长度相比,哪个大就输出哪个(别忘了加上宽度为2的长度),很明显这种做法更加巧妙,按理来说也速度应该更快,但是这道题的数据量不是很大,所以没有明显的作用。

    #include <iostream>
    #include <string.h>
    #include <stdio.h>
    using namespace std;
    int main()
    {
    int T;
    cin>>T;
    while(T--)
    {
        int n,count=0,tmp=0,vol[1001],f[10050]={0},sum=0;
        int a,b,mark=0;
        cin>>n;
        while(n--){
            cin>>a>>b;
            if(a==2){
            count+=b;
            }
            else {
              vol[tmp++]=b;
              sum+=b;
            }
        }
        int v=sum/2; 
        for(int i = 0 ; i < tmp ; i++)  //遍历i件物品
        {
           for(int j = v ; j >= vol[i]; j--)
           {
             int tem = f[  j-vol[i]  ] + vol[i];
             if( f[j] < tem )
                f[j] = tem;
           }
        }
        cout<<(sum-f[v]>f[v]?count+sum-f[v]:count+f[v])<<endl;
    }
     return 0;
    }
     

    其实这道题给我的最大的启发根本不是这道题的知识点,因为背包早就做过,而是每道题的解题方式和方法,其实在ACM这类题中很少有在格式上很严格(一些特殊题型如字符串处理除外),重在算法,所以说一道题没有AC掉的话首先应该想到的是算法的问题(当然这是在边界条件考虑之后的),当时做这道题最大的缺点就是太过相信写的算法了,一心在找边界条件,而忽略了这一点,以后要注意了。。。




  • 相关阅读:
    kubernetes HA 脚本
    架构之数据库分表分库
    架构之高可用性(HA)集群(Keepalived)
    架构之Nginx(负载均衡/反向代理)
    架构之消息队列
    oracle数据迁移
    Oracle中关于清除数据和释放表空间
    疑难杂症:org.hibernate.MappingException: Unknown entity,annotation配置Entity类报错
    j疑难杂症:java.lang.VerifyError: class org.hibernate.type.WrappedMaterializedBlobType overrides final method getReturnedClass.()Ljava/lang/Class;
    疑难杂症:java.lang.AbstractMethodError: org.apache.xerces.dom.DocumentImpl.setXmlVersion(Ljava/lang/String;)V
  • 原文地址:https://www.cnblogs.com/zswbky/p/5431985.html
Copyright © 2011-2022 走看看