暴力求解法之簡單列舉

2021-09-01 18:29:37 字數 3322 閱讀 8868

列舉是暴力求解法最基本最簡單的一種方法,許多問題通過列舉就能找到解。當然,暴力求解法也不是無腦求解問題,通過對問題的分析減少列舉的規模可以使得演算法更加的簡潔和高效。

例1. 輸入正整數n,按從小到大的順序輸出所有形如abcde/fghij=n的表示式,其中a-j恰好為數字0-9的乙個排列(可以有前導0),2≤n

≤79

2\le n\le 79

2≤n≤79

分析問題可知,abcde和fghij正好是0-9的排列,由排列公式a

1010=10

!=

3628800

a_^=10!=3628800

a1010​

=10!

=362

8800

知排列的結果共有3628800種。顯然,直接列舉0-9的排列不是一種高效的方式。如果列舉fghij呢,由排列公式a105

=10!5

!=

30240

a_^=\frac=30240

a105​=

5!10

!​=3

0240

,考慮到n≥2,則fghij中的f≤5,於是列舉的次數應小於c61

a94=

18144

c_6^1a_9^4=18144

c61​a9

4​=1

8144

。這裡n=2是最壞的情況,如果n越大,則列舉的次數越少。但是,列舉fghij的所有可能排列涉及到的排列演算法會消耗大量時間,下面通過列舉fghij所有排列的方法和直接列舉fghij的取值為1000-98765/n的方法進行比較。

(1)fghij直接列舉1000-98765/k所有值

#include

#include

#include

#include

using

namespace std;

int k=7;

intcheck

(int a)

;int b = a*k;

for(

int i=

0; i<

5; i++

)for

(int i=

0; i<

10; i++)if

(flag[i]!=1

)return0;

return1;

}int

main()

int finishtime=

clock()

; cout <<

"----------------> n="

<< k <<

" "<<

(double

)(finishtime-starttime)

/clocks_per_sec <<

"s"<< endl;

return0;

}

2394 16758

2637 18459

4527 31689

5274 36918

5418 37926

5976 41832

7614 53298

14076 98532

----------------> n=7 0.005s

(2)fghij列舉1000-98765/k的可能排列

#include

#include

#include

#include

using

namespace std;

int k=7;

intcheck

(int a)

;int b = a*k;

for(

int i=

0; i<

5; i++

)for

(int i=

0; i<

10; i++)if

(flag[i]!=1

)return0;

return1;

}int dat=0;

void

my_permutation

(int n, vector<

int> vec)

else}}

}int

main()

2394 16758

2637 18459

4527 31689

5274 36918

5418 37926

5976 41832

7614 53298

14076 98532

----------------> n=7 0.072s

從結果可以看出,當n取值為7時,一共有8組結果滿足要求。時間上,第一種方法用時約0.005s,而第二種方法用時達0.072s,顯然第一種方法的耗時最短,實際上,當n取題目中要求的2到79的範圍內,第一種方法都比第二種方法更高效。

例2. 輸入n個元素組成的序列s, 找出乙個乘積最大的連續子串行。如果這個最大的乘積不是正數,應輸出0(表示無解)。1≤n

≤18,−

10≤si

≤10

1≤n≤18, -10≤s_i≤10

1≤n≤18

,−10

≤si​

≤10.

直接列舉所有的起點和終點位置:

#include

using

namespace std;

intmain()

;long

long maxprod=

1, maxtemp=1;

freopen

("data.txt"

,"r"

,stdin);

while

(cin >> n)

maxprod=0;

for(

int start =

0; start < n; start++

)for

(int end = start; end < n; end++)if

(maxprod >

0) cout << maxprod << endl;

else cout <<

0<< endl;

maxprod =1;

}fclose

(stdin);

return1;

}

暴力求解法 之 簡單列舉

1 除法 輸入正整數n,按從小到大的順序輸出所有形如abcde fghij n的表示式,其中a j恰好為0 9的乙個排列,2 n 79.樣例輸入 62 樣例輸出 79546 01283 62 94736 01528 62 分析 列舉0 9的所有排列?沒這個必要。只需要列舉fghij就可以算出abcd...

暴力求解法 簡單列舉

在剛剛開始準備學習些演算法之前,網路上很多演算法高階攻略都會建議先從一些簡單的基本演算法著手入門,其中包括 列舉,貪心,遞迴和分治,遞推,構造,模擬 這些,正好這段時間我在看的劉汝佳的 演算法競賽入門經典 這本書中涉及了很多關於基礎的東西,對於演算法的學習和acm的訓練都很有幫助,所以我打算從 藍書...

暴力求解法 之 列舉排列

1 生成1 n的排列 include includeconst int n 1e3 10 int a n void print permutation int n,int a,int cur int i,j if cur n 遞迴邊界 for i 0 i 2 生成可重集的排列 上面求排列的程式只適用...