zoukankan      html  css  js  c++  java
  • CSU 1547 Rectangle(dp、01背包)

    题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1547

    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

    Hint

    Source

    题意:

      给你n个长方形(其中有宽为1的,也有宽为2的长方形),问你需要一个多大的宽为2的长方形才能将这些小长方形全部圈住(不能旋转长方形,即全部长方形为一个方向)。求最小m。

    题解:

      小长方形宽为2的时候 ans+= b, 直接加。所以我们只要讨论宽为1的小长方形。

      全部的宽为1的长方形我们所要做的就是将它们分成长度尽可能接近的2堆,我们就需要用01背包来解决。

      背包的容量为sum/2(sum为全部宽为1长方形的b的和),每一个长方形的价值为b,当然重量也为b

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <string>
     6 #include <vector>
     7 #include <map>
     8 #include <set>
     9 #include <queue>
    10 #include <sstream>
    11 #include <algorithm>
    12 using namespace std;
    13 #define pb push_back
    14 #define mp make_pair
    15 #define ms(a, b)  memset((a), (b), sizeof(a))
    16 //#define LOCAL
    17 #define eps 0.0000001
    18 typedef long long LL;
    19 const int inf = 0x3f3f3f3f;
    20 const int maxn = 100+10;
    21 const int mod = 1000000007;
    22 int w[maxn];
    23 int dp[maxn*maxn];
    24 void solve()
    25 {
    26     ms(w, 0);
    27     ms(dp, 0);
    28     int n, a, b, ans=0, sum = 0, cnt = 0;
    29     scanf("%d", &n);
    30     for(int i=0;i<n;i++){
    31         scanf("%d%d", &a, &b);
    32         if(a==2)    ans += b;
    33         else w[++cnt] = b, sum+=b;
    34     }
    35     for(int i=1;i<=cnt;i++){
    36         for(int v = sum/2; v>=w[i]; v--){
    37                 dp[v] = max(dp[v], dp[v-w[i]]+w[i]);
    38         }
    39     }
    40     ans += max(dp[sum/2], sum-dp[sum/2]);
    41     printf("%d
    ", ans);
    42 }
    43 int main()
    44 {
    45     #ifdef LOCAL
    46         freopen("jumping.in", "r", stdin);
    47 //      freopen("output.txt", "w", stdout);
    48     #endif // LOCAL
    49     int T;
    50     scanf("%d", &T);
    51     while(T--){
    52         solve();
    53     }
    54     return 0;
    55 }
    View Code

    总结:

    1)了解到了如果将一个数堆分成最接近的2堆,可以转变成01背包。

    比赛时还是靠队友过了XD。

  • 相关阅读:
    sublime界面主题
    html5 初探
    Windows7性能监视器详解
    怎样查出SQLServer的性能瓶颈
    SQL Server资源管理之内存管理篇(下)
    SQL Server资源管理之内存管理篇(上)
    ADO.NET入门教程(八) 深入理解DataAdapter(上)
    ADO.NET入门教程(七) 谈谈Command对象高级应用
    ADO.NET入门教程(六) 谈谈Command对象与数据检索
    ADO.NET入门教程(五) 细说数据库连接池
  • 原文地址:https://www.cnblogs.com/denghaiquan/p/6741491.html
Copyright © 2011-2022 走看看