zoukankan      html  css  js  c++  java
  • SPOJ:Strange Waca(不错的搜索&贪心&剪枝)

    Waca loves maths,.. a lot. He always think that 1 is an unique number. After playing in hours, Waca suddenly realize that every integer can be represented by digit '1', plus operator and minus operator. For example, 1534 can be represented as 1111 + 1 + 111 + 111 - 11 - 11 + 111 + 111. In that case, there are total 7 operators (plus and minus).

    Now, Waca wants to know, what is the minimum number of operators needed to achieve X

    Input

    First row is an integer T, the number of test cases.
    Next T rows will each contain an integer, X, the number given to Waca

    Output

    For each test cases, print an integer, the minimum number of operators needed to achieve X.

    Example

    Input:
    2
    1534
    219 Output: 7
    4

    Constraints:

    • 1 ≤ T ≤ 10
    • 1 ≤ X ≤ 1012

    题意:现在给定一个数N,问最小可以用多少个只含1的数表示出来,输出最小运算次数。比如219=111+111-1-1-1(4=3加+1减)

    思路:首先先尝试贪心,发现没有什么必定的转发法则,而且每种只含1的数出现次数不超过10,而且不可能出现几次正几次负,因为这样都不是最优的。

               所以用搜索来解决,再加一些剪枝。

               搜索:对于当前数N,有三种去向:(以下X只含1,而且位数和N相同,如N=234,X=111;N=4324,X=1111;)

                              1,减若干个X,使得N-cnt1*X刚好大于等于0;  

                              2,减若干个X,使得N-cnt2*X刚好小于等于0;

                              3,用比N高一位的X,减去N。

              剪枝:这样最坏的情况下复杂度是O(T*10*3^12)=5*1e7(其中10是算位数),有些高,注意到第三种情况可以剪枝。假定N有L位,N小于当前5*10^L时,X-N>5*10^L,只会使情况更坏(其中X含L+1个1)

              这样的最坏情况是O(T*10*2.5^12)=5*1e6。再加上次数限制的剪枝,肯定就没有问题了。

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    ll base[]={0,1,11,111,1111,11111,111111,1111111,11111111,111111111,
               1111111111,11111111111,111111111111,1111111111111};
    ll ans;
    void dfs(ll N,ll times){    
        if(times>ans) return;
         if(N==0){ if(ans>times) ans=times;return ;}    
        ll tmp=N,L=0;
        while(tmp){ L++; tmp/=10;}
        if(N/base[L]) dfs(N-(N/base[L])*base[L],times+N/base[L]);    //避免死循环    
        dfs((N/base[L]+1)*base[L]-N,times+N/base[L]+1);
        if(N>=(base[L+1]-base[L])/2)dfs(base[L+1]-N,times+1);  //剪枝 
    }
    int main()
    {
        int T; ll N; cin>>T;
        while(T--){
            ans=100000000;
            scanf("%lld",&N);
            dfs(N,0);
            printf("%lld
    ",ans-1);
        }
        return 0;
    }
  • 相关阅读:
    OAF_文件系列8_实现OAF处理Excel的JXL包详解
    OAF_文件系列7_实现OAF处理Excel的JXL包介绍(概念)
    OAF_文件系列6_实现OAF导出XML文件javax.xml.parsers/transformer(案例)
    Kafka SSL安装与配置
    如何构建推荐系统
    Flink消费Kafka到HDFS实现及详解
    Kafka网络模型和通信流程剖析
    Kafka日志压缩剖析
    Kafka Eagle安装详情及问题解答
    Kafka幂等性原理及实现剖析
  • 原文地址:https://www.cnblogs.com/hua-dong/p/8933530.html
Copyright © 2011-2022 走看看