1. 程式人生 > >SPOJ:Strange Waca(不錯的搜索&貪心&剪枝)

SPOJ:Strange Waca(不錯的搜索&貪心&剪枝)

main lld 相同 unique ber namespace 表示 sin lib

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\n",ans-1);
    }
    return 0;
}

SPOJ:Strange Waca(不錯的搜索&貪心&剪枝)