所谓筛选法就是从全集中将不合格的项全部删去,剩下的就是答案。- ~ t: M2 I+ s; N" F
- x% @& D, x, U7 m
1: 求1-100之间的质数5 }# `. ?6 q$ j; j7 r
4 _- S) G* ]) j. E+ D
原理:先将2的倍数全部划掉,再将3的倍数全部划掉……直到将10的倍数全部划掉(10^2 = 100 )。剩下的就是质数.: n3 {. r" q' S' C' V2 _+ E. {5 q1 L$ i
. Y' k8 ~: q3 n2 z6 ivoid fun1() ! o- p1 _" b" l S5 t{1 o% d1 J. ~7 {
int i, j; . g2 h4 l& `$ n; ~7 v2 Y5 H6 W1 w9 p bool flag[100];! I6 s" g4 d$ L; K
1 p; r3 C* ^& f3 M1 c5 C7 l for ( i = 2; i < 100; i++ )5 V1 y. B! D) }3 _$ c& j A) H
flag = true;: M1 j/ K {1 O4 d) s b. b
6 V- D: k) O( N. f //下面开始划掉合数4 O1 k7 W: z) a2 J4 n4 _
for ( i = 2; i < 10; i++ ) //因为合数的最小正因数不大于它的平方根. m% g+ L2 ]0 p( I
{ 4 B# x) R$ c7 q/ X. E1 T# C if ( flag == false )9 q1 s( ~( a! K3 C' o. C' x7 B
continue; //既然i已经是合数,它的倍数应该已经被划掉9 {6 t4 j4 H! K& P3 O) n
for ( j = 2; j * i < 100; j++ )//划掉i*j + R3 ~" |8 W) F* Y9 I flag[i*j] = false; ' x5 B+ p# t- C/ t8 n# J0 M } ) f' ^1 E6 c: U" k# ~- r6 r% |) w+ d+ X% Y7 ]+ o* K
//输出结果1 D o( K% b0 }8 M# L& t6 n2 p
for ( i = 2; i < 100; i++ ) . ^3 O; h O' l3 N' M if ( flag ) ; i) m- i' T6 y) B cout << i << ' ';; n: m6 J s" R) o
}3 ?& G3 @/ U! s. t; P+ c
- o* k3 b w/ u& ?& O* d2 G
2: 30个人站成一圈,从第一个人开始报数,凡报到5的拉出去毙了,剩下的人接着从1开始报,直到只剩一人放掉。想活命该站哪?8 V! v. M( B5 L# O
6 `- a1 g% ~& s+ X$ z 这是个经典问题,解法就是模拟整个过程,有点类似于循环队列。 & y/ f$ G$ z& f2 s: W/ Q0 @ " G0 v+ |4 x6 R4 C9 y+ f! E 另外,为了程序上处理方便,可以假定所有的人都拉去毙了,然后看一下最后一个被毙掉的是谁。另一处为了处理方便而采取的措施是pos的初始值设为-1.很多时候,对问题的问法稍作变动,或者将初始值、加减变量的位置稍作调整,用程序处理起来会方便很多。 ' F6 i- n4 I& d# P/ K: n ' D7 t, x- _$ {0 z$ B* e! \3 Ovoid fun2()7 _$ S- R2 N* \; c1 g
{( h: n3 [) n W5 L4 e3 g, w0 w
bool flag[30];//标记第i个人的状态,false已被毙掉,true还没被毙掉 3 x& a0 i: n# p2 R7 ^( P* y 7 z( Z9 @" Y9 O# B" |: X; {; b for ( int i=0; i< 30; i++ )0 K2 F; K! I* k G: {3 @* d
flag = true; ) Z# z5 j9 M, @% c% c8 p$ v" d$ s( S" {' h. {( l0 _5 d
int n = 30;//还剩几个人 9 @4 G: p! C0 K/ |' t# W int cnt; 2 O) B3 \% P1 X+ f# k- M. b int pos = -1;//初始值不一定从0开始,设为-1处理起来较方便 ( I4 _, m6 Q# F while ( n > 0 )7 S3 K4 i7 x9 U) p6 ^
{& F0 u1 O$ H; H# l1 g9 \* f: e/ ~
cnt = 0; / P$ P' D( u! L% ? while ( cnt < 5 ) 4 D- }: f X9 ]$ T1 `; Y { ; @- x; k- n" w, P) f' c$ v( Q if ( ++pos == 30 ) 3 ~) t* W+ _( B/ j- F pos = 0;2 @4 ] E1 l# {' _7 }* O2 w5 w' ?
if ( flag[pos] )//此人还没被毙掉 " i# p+ Q" C" m: N, Y/ R; H6 Z0 l cnt ++; ; }/ K3 N' s C1 f0 M! } } 2 A2 j) |) K! y! S. { //退出时cnt == 5,pos指向报5的人4 ?* V9 `# \, D8 x/ ~3 O
flag[pos] = false;//毙掉& N+ @. B6 P: p4 y j( \2 n# y1 o$ O+ l
n --;//剩余人数减1 " P4 `# X" @- k7 [- | }7 F0 \/ E9 F$ C, ]
//最后一个被毙的就是幸存者 , h! Y$ L: Z5 q //之所以加1是因为程序中从0开始计数,输出却以1开始计数7 @; P' k c. E$ E0 |
cout << pos + 1 << ' '; 4 D5 R3 E7 ]+ T& d- x4 ?}" H$ U! h" y( C! w
{+ `& h. i) _ y) S5 p
3: 一个数被5除余3,被7除余2,求此数最小为几。 % h7 j9 y2 P8 D/ R 2 Z1 _1 [% c+ q7 ~/ H! Z 筛选法不一定非要标记true/false,有时候也可以使用计数来进行筛选,这个问题就是一例。8 S7 f3 b- ?5 w0 X( }
首先,如果问题有解,则解必小于 5 * 7 = 35,只用在此范围内筛选即可。" g% G9 s8 O- s
在程序处理上,如果一个数满足一个条件,就将计数值加1,最后计数值为3的即为所求。# F. K- h; o* C; E( z
6 Y2 n" h b: n! Dvoid fun3()+ k1 c# \1 D4 @: t( l. g, a
{ 8 f+ p- d& T6 t2 D int a[105];//105 = 5 * 79 w% e* X; ^$ o5 ~4 D
int i; ) u% x4 M5 O, a# n8 O //计数清0 0 K) Y: E0 _! m/ {5 z) z, } for ( i = 0; i < 35; i++ ) " a& v2 j4 N, a6 }, _# e a = 0; * l+ ]. f: V* ^3 q //开始筛选+ r: \7 K( J8 u1 P
for ( i = 3; i < 35; i += 5 ) # `; J W8 J& n" f a ++; 1 o( Q# z! ?. b* B' l for ( i = 2; i < 35; i += 7 ) / j% u% I7 k! M7 F/ M0 L! _ a ++;% P9 [3 Q/ b; b9 ~# c& J% l
- q) d! H: ?9 l/ u& J/ U) j for ( i = 0; i < 35; i++ )- u% X% A2 W# H4 J# b% `
if ( a == 3 )3 x) l1 U/ g1 Q4 L5 E8 G
{ - _7 ~2 T9 g8 ^ cout << i << endl; % X9 [# S f3 V& G return;- p) c' o1 n% g# ^" X" D0 Q
} 7 k+ K7 l' F0 }6 `: Z //如果执行到这里说明无解& S% g# Z: m- _1 V6 F ~
cout << "No Answer!" << endl;. A9 R+ h, r( A2 V
}) t4 |7 R* ^1 _9 j+ A$ ^$ Q
7 c d; R+ g& V! x! y- V( q( j
; N- q1 o8 J% a# I总结:0 i. E( ?3 X3 L
筛选法的时间效率较高,但需要一个辅助数组,这就意味着对规模很大的问题不适用。例如第3个问题,条件多1个,需要的空间就翻几倍。解决的办法是: 4 C5 e% r4 D8 n. s+ D) X 6 b7 x& P. y7 k4 I4 {for ( int i = 0; i< n; i++ ) 6 V- |) J- {. o z. J* A{ ) p/ B' A. ?: o& E3 f% e if ( i % 5 == 3 && i % 7 == 2 && ... ): J, |8 k, A, `9 ]3 n
cout << i; - s3 @4 z$ I' n/ v, f2 Q0 U Z} . a8 y. D J w9 q8 z 但相应的,这样做速度就慢了下来。所以还得根据问题的规模来决定使用什么方案。 i. @/ J5 S9 G; q ?7 v- C( b
$ ?5 C _; _3 H2 s) [4 g* V7 n0 p$ w 总体来讲,对于可以条件判断较复杂,且根据前一个(不)符合条件的情况较简单的推出下一个(不)符合条件的情况,(不)符合条件的情况分布较稀疏的问题,用筛选法速度较快。如果第3题中加一个条件被2除余1,用筛选法就不太合算了。 ( `- N7 o! O, K0 }- N8 \4 T, m ( I8 _! _* |& O4 n" I! \0 j 最后说明一下,此次给出的程序目的在于说明方法,在效率并不是最高的