zoukankan      html  css  js  c++  java
  • CH5E07 划分大理石【多重背包】

    5E07 划分大理石 0x5E「动态规划」练习
    描述
    有价值分别为1..6的大理石各a[1..6]块,现要将它们分成两部分,使得两部分价值之和相等,问是否可以实现。其中大理石的总数不超过20000。

    输入格式
    有多组数据!
    所以可能有多行
    如果有0 0 0 0 0 0表示输入文件结束
    其余的行为6个整数

    输出格式
    有多少行可行数据就有几行输出
    如果划分成功,输出Can,否则Can't

    样例输入
    4 7 4 5 9 1
    9 8 1 7 2 4
    6 6 8 5 9 2
    1 6 6 1 0 7
    5 9 3 8 8 4
    0 0 0 0 0 0
    样例输出
    Can't
    Can
    Can't
    Can't
    Can

    题意:

    有六种石子,价值是1-6,每种石子有一个数量。现在想把他们平分为价值相等的两堆,问是否可行。

    思路:

    首先统计一下总的价值,如果价值是奇数,肯定是不行的。

    如果价值是偶数,就是一个多重背包问题。

    所以先把每种石头用二进制拆分,价值即是价值又是重量。最后看dp[mid]是否等于mid就可以了。

     1 //#include <bits/stdc++.h>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<stdio.h>
     6 #include<cstring>
     7 #include<vector>
     8 #include<map>
     9 #include<set>
    10 
    11 #define inf 0x3f3f3f3f
    12 using namespace std;
    13 typedef long long LL;
    14 
    15 int stone[10], dp[300010];
    16 int num[300010], cnt;
    17 
    18 
    19 void split(int n, int v)
    20 {
    21     int x = 1, tmp = 0;
    22     while(tmp <= n){
    23         num[cnt++] = x * v;
    24         x *= 2;
    25         tmp += x;
    26     }
    27     x = n - tmp;
    28     if(x){
    29         num[cnt++] = x * v;
    30     }
    31 }
    32 
    33 
    34 int main(){
    35     while(true){
    36         int sum = 0;
    37         for(int i = 1; i <= 6; i++){
    38             scanf("%d", &stone[i]);
    39             sum += stone[i] * i;
    40             //dp[i][0] = true;
    41         }
    42         if(sum == 0){
    43             break;
    44         }
    45 
    46         if(sum % 2){
    47             printf("Can't
    ");
    48             continue;
    49         }
    50 
    51         cnt = 0;
    52         for(int i = 1; i <= 6; i++){
    53             split(stone[i], i);
    54         }
    55         memset(dp, 0, sizeof(dp));
    56         int mid = sum / 2;
    57         for(int i = 0; i < cnt; i++){
    58             for(int j = mid; j >= num[i]; j--){
    59                 dp[j] = max(dp[j], dp[j - num[i]] + num[i]);
    60             }
    61         }
    62 
    63         if(dp[mid] == mid){
    64             printf("Can
    ");
    65         }
    66         else{
    67             printf("Can't
    ");
    68         }
    69     }
    70     return 0;
    71 }
  • 相关阅读:
    FDR校正
    PHP base64 编码转化图片并进行指定路径的保存和上传处理(转自https://cloud.tencent.com/developer/article/1333877)
    google网页评测工具
    链接类型:预加载
    鼠标经过时显示、隐藏提示
    thinkphp5导入excel数据
    JS消息窗口滚动到底部
    datatable分页使用箭头
    Mysql基础
    php-MD5/sha1
  • 原文地址:https://www.cnblogs.com/wyboooo/p/9778638.html
Copyright © 2011-2022 走看看