所谓筛选法就是从全集中将不合格的项全部删去,剩下的就是答案。2 F4 `% H+ F5 Q3 \1 ]4 M( D7 G
( e& v) L0 n7 {# R. r7 z( \! v
1: 求1-100之间的质数8 Q$ |0 M1 ` H# }" b, R
0 Q) z2 y+ `; n7 z+ M4 Z
原理:先将2的倍数全部划掉,再将3的倍数全部划掉……直到将10的倍数全部划掉(10^2 = 100 )。剩下的就是质数.2 V( k! M. _! |# w
; \0 ~+ i1 z1 [) b; X5 _void fun1()( R" n2 y, C+ F
{; [3 M2 [; A! y4 X7 T/ s; R; r: P
int i, j; 4 K7 m A( S: w c6 F8 F2 ~ bool flag[100]; # }% U: F O( P& c X+ M9 W \; ~& s1 `1 [
for ( i = 2; i < 100; i++ ) 2 O2 T* U# D8 Q% _ M4 q7 l flag = true; 6 H) [& Q# O6 E5 t# p% V. O, {) f; f' O
//下面开始划掉合数 1 @' K+ @3 K4 v5 ]- H for ( i = 2; i < 10; i++ ) //因为合数的最小正因数不大于它的平方根 9 b: e5 D H6 c# n) ]& ^ {1 x9 g, d" D4 p# p4 {8 F
if ( flag == false ) ; g4 e E: e5 O& L/ e k- V8 \ t continue; //既然i已经是合数,它的倍数应该已经被划掉 6 f* L4 u( d) y' Z8 {. s for ( j = 2; j * i < 100; j++ )//划掉i*j 4 z; `" e4 U" [. E( b flag[i*j] = false;: J, Q4 M2 G; o3 s3 L
}$ w6 x# _# _. z, O9 y
: @- F( \+ h3 P" b" ]8 `
//输出结果% ?4 f9 Q' n7 C. P$ `, I
for ( i = 2; i < 100; i++ ) ' }% t% O; N# M9 [ if ( flag )$ N- w$ y! q6 \, Z- I/ P7 s
cout << i << ' ';( Z$ G, d& v7 k; u8 H) C* ^' o
}# P, c7 [5 g& G1 o4 U4 N) O7 {
, Y& Q5 P" R6 d. N- z# h, k2 }2: 30个人站成一圈,从第一个人开始报数,凡报到5的拉出去毙了,剩下的人接着从1开始报,直到只剩一人放掉。想活命该站哪?5 l# u8 X, } E( @8 R6 k
/ V# N+ d) Z: X( A' T+ b 这是个经典问题,解法就是模拟整个过程,有点类似于循环队列。4 ~: v$ C7 H) I& E# w. U
/ t5 x9 r3 W$ d+ K5 ~+ `$ q+ l 另外,为了程序上处理方便,可以假定所有的人都拉去毙了,然后看一下最后一个被毙掉的是谁。另一处为了处理方便而采取的措施是pos的初始值设为-1.很多时候,对问题的问法稍作变动,或者将初始值、加减变量的位置稍作调整,用程序处理起来会方便很多。0 _& s1 [! y, y( A. h
3 V9 d. A; D9 Jvoid fun2()" Z( a7 [ T: a* j
{ $ z% c9 D: W+ Y w8 @ bool flag[30];//标记第i个人的状态,false已被毙掉,true还没被毙掉 & M" B% ]7 c1 l( y" |7 F' ^' |4 l; J, d+ N \2 c H
for ( int i=0; i< 30; i++ )/ y9 g6 h8 L8 J5 J9 @& g
flag = true; & m2 Z( }/ p2 E# z/ A+ W# S0 \ w5 m' L" c- ^
int n = 30;//还剩几个人 4 M9 `5 o: b" H9 s( q int cnt;0 u) u: [" P, T6 H0 q
int pos = -1;//初始值不一定从0开始,设为-1处理起来较方便 ; K/ ~ ~7 T* `( I4 u: c8 |: W while ( n > 0 ) " D4 {3 V# n ]% U% W& s5 P { W2 O( o2 c3 ?) p8 q8 k2 N cnt = 0; 3 Q# H* Q3 e& x" } D" O# v5 q while ( cnt < 5 ) . F( e! ~' w3 S2 v& s- X( n { ! m2 X0 B) b; h1 y) d# ?2 c, ^5 L3 i if ( ++pos == 30 )% W5 u y5 j8 G! Q
pos = 0; $ u! A. E, x @9 Q% n% m9 u if ( flag[pos] )//此人还没被毙掉" O, u, q7 k9 S! b( P& w
cnt ++;( \/ h0 k8 A; I% i! K' E) M! u
}. J' b! O- g+ M" u( q" ` L" P. _+ D U# m
//退出时cnt == 5,pos指向报5的人8 m' B# X# n# J( u
flag[pos] = false;//毙掉 6 ]8 J( t# P1 D R n --;//剩余人数减1 3 R# V) W" {1 i5 U0 B }0 f. e: Q: q) P
//最后一个被毙的就是幸存者. |2 E: p1 T# I+ `% O
//之所以加1是因为程序中从0开始计数,输出却以1开始计数. o! n' W* n3 U
cout << pos + 1 << ' ';+ N' o8 a* W. m h5 K+ O
}& S; t( v! W; v: {% t! K
- i) h( M% w- ~. l' a K1 c8 d* `3: 一个数被5除余3,被7除余2,求此数最小为几。3 Y: H& o- r/ f
; `+ r J. v8 L w+ X 筛选法不一定非要标记true/false,有时候也可以使用计数来进行筛选,这个问题就是一例。 . M* X3 \5 w' a- m- E' L L' [ 首先,如果问题有解,则解必小于 5 * 7 = 35,只用在此范围内筛选即可。 9 `/ z8 w& N. D( {5 e 在程序处理上,如果一个数满足一个条件,就将计数值加1,最后计数值为3的即为所求。6 }$ K h4 s1 M. e
7 _6 I: a2 Z& u- rvoid fun3()9 ^2 }+ t/ f+ _+ \
{ 9 j0 r3 `( x* B1 z5 ^2 I" t int a[105];//105 = 5 * 7 - |) D2 O3 k4 {2 x) Q2 \ int i;( R/ T) |0 ^% J! m5 B% w
//计数清0 ' E) }7 ? b2 n7 M for ( i = 0; i < 35; i++ )1 X& ^6 O5 g3 t% N, A& U! E& Q
a = 0;6 a; L' D- t' m# T2 A. m
//开始筛选2 M1 z" X3 k* H* J5 D
for ( i = 3; i < 35; i += 5 )' S& p: d, b+ U0 v8 i0 i
a ++;: f4 E n4 G' H
for ( i = 2; i < 35; i += 7 )/ z3 s4 Y: M& W( N5 r
a ++; / n+ {! `* G) g6 ^* E1 Y3 s7 R7 L3 y$ m* q* f7 u) ^
for ( i = 0; i < 35; i++ )' d/ f4 F7 T7 G1 i$ x1 T
if ( a == 3 ) / H1 T F9 x2 ]1 p" c { 5 q* C1 B! u. G1 j8 } cout << i << endl; ) V9 h' c' L0 p- P% a( B" ^ return;0 |2 T' h4 D5 r0 {
} ) U" Q0 p: g/ ]" |; y //如果执行到这里说明无解 7 t F8 g7 V; Y6 C2 G cout << "No Answer!" << endl;4 \# |5 C& H3 Z6 [/ b C
} " j$ f3 J% _2 U . I: w7 w; V& u& Z 6 s) [ C! y0 R* G+ ^总结: " d' D& y1 K( B$ t 筛选法的时间效率较高,但需要一个辅助数组,这就意味着对规模很大的问题不适用。例如第3个问题,条件多1个,需要的空间就翻几倍。解决的办法是: / X8 v2 [6 U% f0 J9 y * j4 i0 n0 }; o! nfor ( int i = 0; i< n; i++ )7 m" D/ Y$ `+ i: \7 {- F0 N* r
{- W, w6 @9 d/ e5 [. e
if ( i % 5 == 3 && i % 7 == 2 && ... )( n; K. t: ~8 y
cout << i; 0 d. u+ M% I( p. [" H}: Z0 H- q3 i) P7 F* w, r$ e7 X
但相应的,这样做速度就慢了下来。所以还得根据问题的规模来决定使用什么方案。 0 b: Y$ r3 k9 n1 P b* x# R. ^ ?3 w8 ^6 c7 H% ]' R! j9 [# I
总体来讲,对于可以条件判断较复杂,且根据前一个(不)符合条件的情况较简单的推出下一个(不)符合条件的情况,(不)符合条件的情况分布较稀疏的问题,用筛选法速度较快。如果第3题中加一个条件被2除余1,用筛选法就不太合算了。/ Z$ y, k, t: Y% j! g& m& C# j