zoukankan      html  css  js  c++  java
  • POJ 1416 -- Shredding Company

     POJ 1416 -- Shredding Company

    题意:

    公司现在要发明一种新的碎纸机,要求新的碎纸机能够把纸条上的数字切成最接近而不超过target值。比如,target的值是50,而纸条上的数字是12346,应该把数字切成四部分,分别是1、2、34、6。因为这样所得到的和43 (= 1 + 2 + 34 + 6) 是所有可能中最接近而不超过50的。(比如1, 23, 4, 和6 就不可以,因为它们的和不如43接近50,而12, 34, 6也不可以,因为它们的和超过50了。碎纸还有以下三个要求:

    1、如果target的值等于纸条上的值,则不能切。
    2、如果没有办法把纸条上的数字切成小于target,则输出error。如target是1而纸条上的数字是123,则无论你如何切得到的和都比1大。
    3、如果有超过一种以上的切法得到最佳值,则输出rejected。如target为15,纸条上的数字是111,则有以下两种切法11、1或者1、11.
    你的任务是编写程序对数字进行划分以达到最佳值。

    解题思路:
    DFS

    (1)比如一个6位数n,切成为6个数的话,这6个数的和如果大于目标数target则不用再搜索了,因为这肯定是所有划分中和最小的,而最小都比目标数大,自然就没有合要求的答案了.
    (2) 如何切分,假如以50  12346 为例。
    第一步,先切下一个“1”,然后递归去切“2346”;
    第二步,再切下一个“12”,然后递归去切“346”;
    第三步,再切下一个“123”,然后递归去切“46”;
    第四步,再切下一个“1234” 然后递归去切“6” 
    第五步,再切下“12346”。

    (3)切下来的 前面的数字串部分 则加入到划分的和,剩下的部分继续递归,直到已经划分出来的数字长度len等于数字串总长度strlen(num)。为了记录划分方式,使用int数组devide记录每一次划分的长度,比如样例50 12346划分为43 1 2 34 6,那devide[0] = 1,devide[1] = 1,devide[2] = 2,devide[3] = 1。而且为了保存最优解,需要在已经划分出来的数字长度len等于数字串总长度strlen(num),并且abs(bestx-target)>abs(sum-target)时,更新最优解bestx = sum,并且将devide转存到ansdevide中,为了方便之后答案的输出。

    (4)使用字符数组存储数字串num,这样在搜索时,只要控制字符数组的起止位置就可以模拟数字串的拆分。

    (5)剪枝方法:在搜索时若发现部分和 大于(不能等于)target时,则可结束搜索。

    在进入dfs搜索时,可以把特殊情况排除

      1)error的判定要在搜索前进行

      2)当数字串num和target相等时,直接输出,不用划分

      3)当数字串的每一位数字之和sum2等于target时,直接逐位输出,每个数字为一个划分

         注意这种情况有一个特例,就是0出现的时候,

        例如样例:6 1104

        它的最优划分有两种 6 1 1 0 4

                  6 1 1 04

        所以此样例应该输出rejected

        所以这种情况下,应该保证数字串num中没有0,才可以直接逐位输出

    (6)rejected(多个最优解)的判定要在搜索后判定。当最优解出现两次的时候(出现abs(bestx-target)==abs(sum-target)),使用全局变量Count计数

     

     1 #include<iostream>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 int target;
     6 char num[10];
     7 int bestx;
     8 int Count;
     9 int anslen;
    10 int ansdevide[10];
    11 void dfs(char *ch,int len,int sum,int c,int *devide)
    12 {///len为当前已经划分的数字串的长度,sum为当前已划分的数字的总和
    13 ///c为划分的数字的块数
    14     if(len == strlen(num))
    15     {
    16         if(abs(bestx-target)>abs(sum-target))
    17         {
    18             Count=0;
    19             anslen = c;
    20             bestx = sum;
    21             for(int i=0;i<c;i++)
    22                 ansdevide[i] = devide[i];
    23             return;
    24         }
    25         if(abs(bestx-target)==abs(sum-target))///出现多个最优解
    26         {
    27             Count++;
    28         }
    29         return;
    30     }
    31     for(int i=1;i<=strlen(ch);i++)
    32     {///确定下一步划分的长度i
    33         int newsum = 0;
    34         for(int j=0;j<i;j++)
    35             newsum = newsum*10 + (ch[j]-'0');
    36         newsum+=sum;
    37         devide[c] = i;
    38         if(newsum<=target)
    39             dfs(ch+i,len+i,newsum,c+1,devide);
    40     }
    41 }
    42 
    43 int main()
    44 {
    45     while(cin>>target && target)
    46     {
    47         cin>>num;
    48         int sum1 = 0;///计算纸上的数是多少
    49         int sum2 = 0;///每一位的和
    50         for(int i=0;i<strlen(num);i++)
    51         {
    52             sum1 = sum1*10+(num[i]-'0');
    53             sum2 += num[i]-'0';
    54         }
    55         if(sum1 == target)
    56             cout<<target<<" "<<target<<endl;
    57         else if(sum2 > target)
    58         {
    59             cout<<"error"<<endl;
    60         }
    61         else if(sum2 == target && !strchr(num,'0'))
    62         {
    63             cout<<target;
    64             for(int i=0;i<strlen(num);i++)
    65             {
    66                 cout<<" "<<num[i];
    67             }
    68             cout<<endl;
    69         }else
    70         {
    71             Count = 0;
    72             bestx = 0;
    73             int devide[10];
    74             dfs(num,0,0,0,devide);
    75             if(Count > 0)
    76                 cout<<"rejected"<<endl;
    77             else{
    78                 cout<<bestx;
    79                 int temp=0;
    80                 for(int i=0;i<anslen;i++)
    81                 {
    82                     cout<<" ";
    83                     for(int j=temp;j<temp+ansdevide[i];j++)
    84                     {
    85                         cout<<num[j];
    86                     }
    87                     temp += ansdevide[i];
    88                 }
    89                 cout<<endl;
    90             }
    91         }
    92 
    93     }
    94     return 0;
    95 }

  • 相关阅读:
    二分查找算法
    java多线程模拟停车位问题
    ECShop模板原理
    linux 常用命令 自己 积累
    ubuntu忘记root密码解决
    centos下一键安装lamp环境,快捷,方便
    腾讯php部分面试题答案
    PHP面试题集
    php笔试题
    流行的php面试题及答案
  • 原文地址:https://www.cnblogs.com/yxh-amysear/p/8463343.html
Copyright © 2011-2022 走看看