- 在线时间
- 0 小时
- 最后登录
- 2004-7-22
- 注册时间
- 2004-5-28
- 听众数
- 1
- 收听数
- 0
- 能力
- 0 分
- 体力
- 124 点
- 威望
- 0 点
- 阅读权限
- 20
- 积分
- 43
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 4
- 主题
- 7
- 精华
- 0
- 分享
- 0
- 好友
- 0
升级   40% 该用户从未签到
 |
所谓筛选法就是从全集中将不合格的项全部删去,剩下的就是答案。
( p! C5 H1 Z/ c1 ]. |/ d" C5 b- m
6 F) U$ H/ F2 ~( P* K0 R1: 求1-100之间的质数
4 @/ n% V7 s# p. J) `, a$ |9 h4 `7 S5 g2 l! l
原理:先将2的倍数全部划掉,再将3的倍数全部划掉……直到将10的倍数全部划掉(10^2 = 100 )。剩下的就是质数.
5 a, @! O. r' T
4 Y# j; e% `4 b$ i% _ m% n) v" T. Ivoid fun1()' P6 f2 i+ D( X4 s" K
{
X( D6 Q: u o int i, j;
" z/ Y4 w2 L* b. L bool flag[100];( T2 ^5 \6 e- h4 x
+ W8 O' n+ T) \2 G7 x4 p for ( i = 2; i < 100; i++ ) \9 \4 K1 F- O! `; |9 W# J. C) ]3 F
flag = true;0 m5 w+ H' m2 p; B k# {
' a; n4 }8 \5 @
//下面开始划掉合数, i* Z, z$ H* ~& V8 U- h# m
for ( i = 2; i < 10; i++ ) //因为合数的最小正因数不大于它的平方根, q- N E J8 G M
{+ J0 u G/ y; u- w$ O! E
if ( flag == false )) @8 w2 d! d! i; u" Q
continue; //既然i已经是合数,它的倍数应该已经被划掉) o; o9 V% |5 z, b' c1 w L
for ( j = 2; j * i < 100; j++ )//划掉i*j( k7 p; z0 F P% y8 M! H
flag[i*j] = false;
* Q* K9 D+ K' v" V% n$ E( N8 W9 G }
; E; V: Q; n1 [2 r( _ Q- m$ Z; S- u6 J# E- E8 u6 T) ?2 M
//输出结果
5 K& x* b) d1 B- m' \ for ( i = 2; i < 100; i++ )
7 P$ e9 ]; T6 |3 J if ( flag )8 c2 @% `2 d% Y8 d. d9 T
cout << i << ' ';4 {/ n3 d' ~- U" _
}4 ?1 R8 e( t! N; t* e
% X& i+ l* L; J8 P5 ^2: 30个人站成一圈,从第一个人开始报数,凡报到5的拉出去毙了,剩下的人接着从1开始报,直到只剩一人放掉。想活命该站哪?
7 D/ s/ y" Z# U; S/ O+ d( W2 d
2 a P( U8 L: n2 l5 R; |8 b# p5 { 这是个经典问题,解法就是模拟整个过程,有点类似于循环队列。$ ^7 r: y7 i" @/ F' \; X$ \
0 `' ]9 l6 S, @" e
另外,为了程序上处理方便,可以假定所有的人都拉去毙了,然后看一下最后一个被毙掉的是谁。另一处为了处理方便而采取的措施是pos的初始值设为-1.很多时候,对问题的问法稍作变动,或者将初始值、加减变量的位置稍作调整,用程序处理起来会方便很多。# Y" b+ `! k1 Z+ }# s Z9 U
/ z" H+ N8 {! x& [
void fun2()3 f6 ^1 M- z! [& p
{' ]8 L/ `- g/ a* D# G/ O
bool flag[30];//标记第i个人的状态,false已被毙掉,true还没被毙掉
2 D& @# q6 S$ d) m4 j7 p' t9 ?" J! c, P* I3 S/ e
for ( int i=0; i< 30; i++ )- S$ L7 m( O5 J
flag = true;
* u6 w$ w; V& y6 g- K* S7 M2 K1 y) T0 k' O
int n = 30;//还剩几个人
0 i* D" S% T: k# ]% @7 E int cnt;: H. {" E% K& y# V) H- Y
int pos = -1;//初始值不一定从0开始,设为-1处理起来较方便8 o7 y5 D& ]5 k" W
while ( n > 0 )
% |& r, l3 h& Z2 W' L- J {
A+ n! Y5 t8 D% _ cnt = 0;% \ i% I# D1 [& q8 T+ }
while ( cnt < 5 )7 P# ]7 @& |. b; t7 a2 q
{ B X$ S& V& e9 t
if ( ++pos == 30 )3 z# R; L6 { r9 s9 Q
pos = 0;
- W0 t5 G l( l5 N( F0 L if ( flag[pos] )//此人还没被毙掉0 a r8 t4 u! f
cnt ++;
. I. w: k% b2 f) X }8 L$ _4 e. h+ O" ?! ?
//退出时cnt == 5,pos指向报5的人$ [; v7 M! z1 j4 |) i
flag[pos] = false;//毙掉% x2 T3 w6 Z# t/ Y5 g
n --;//剩余人数减15 P( ~/ a& B7 M/ G& |
}
% i0 `1 u0 B/ A0 r( C- c$ _ //最后一个被毙的就是幸存者
3 p$ N8 s5 q# c- P4 j! G. T& L //之所以加1是因为程序中从0开始计数,输出却以1开始计数
( r+ D6 d' O; P, ^! ~8 Q cout << pos + 1 << ' ';- E; N- g; e/ L2 _6 f! s2 }1 U. Z8 u
}. ?1 A+ p) g# o( `' l' U5 c
. c, X% p! E+ F9 X3: 一个数被5除余3,被7除余2,求此数最小为几。
+ T5 G* {$ J) S+ J" U0 j# z& X" |' |
筛选法不一定非要标记true/false,有时候也可以使用计数来进行筛选,这个问题就是一例。
" l4 j4 J- o1 | 首先,如果问题有解,则解必小于 5 * 7 = 35,只用在此范围内筛选即可。4 d2 v; Z& B# ?8 e) A
在程序处理上,如果一个数满足一个条件,就将计数值加1,最后计数值为3的即为所求。7 Z( e b6 A2 K" d
8 X( n. s) I/ F; E3 Xvoid fun3()
R7 o; c* L+ e1 x3 ~& ^% w{! \. ]! o+ i$ ]2 `$ @
int a[105];//105 = 5 * 7
8 ^: X# l6 z6 i- N int i;. h* O G" c$ D, q6 H! }' z
//计数清0
( U1 y: k! Y3 {+ e' D& z for ( i = 0; i < 35; i++ ): \# _$ b4 U/ w5 Q
a = 0;
5 y! X' P. g$ |9 N //开始筛选
9 ~0 ^2 z; H( q& B for ( i = 3; i < 35; i += 5 )
5 t0 O& A+ r+ F a ++;! Q- Q/ ~& j! @ }; ?# M, b
for ( i = 2; i < 35; i += 7 )8 K$ g! B, \* F
a ++;, ^' E4 F8 ~' X8 j) K
' a3 j! A5 U* ~$ y
for ( i = 0; i < 35; i++ ), Q1 F6 d9 ~4 W2 h% h! q* J0 x( N$ p
if ( a == 3 )
1 e3 [+ v0 _4 o8 @/ p {
# u; w6 z. V- h% {- E4 z" h$ V cout << i << endl;
& G# y, d: C( R& p6 i( i: B1 A1 b return;
4 z% \7 U. L. q }
3 k9 ]/ j o8 A9 H //如果执行到这里说明无解# [6 u7 n' a5 e, K7 j: d
cout << "No Answer!" << endl;
. j& T8 i- `) d7 F+ w' I. a+ l}
u* k# T, B# u! H! v, D, S* t* O3 D- }! `# J) V6 |6 L7 O
0 `2 w7 `' @- _; p# D9 n总结:
6 |; L" C' Z" o# H4 j 筛选法的时间效率较高,但需要一个辅助数组,这就意味着对规模很大的问题不适用。例如第3个问题,条件多1个,需要的空间就翻几倍。解决的办法是:- ?# Q) i6 q$ I
. Q' n4 s n/ s y1 Z7 ^
for ( int i = 0; i< n; i++ )- b+ i8 l) o" ^5 ^6 f
{
7 D i7 b, S5 u# W0 s/ A. J+ o$ F if ( i % 5 == 3 && i % 7 == 2 && ... )0 e4 ^" u" }3 }' G2 v
cout << i;
: G+ r+ j/ w( k; w4 a}* M8 k5 W6 _0 o8 n: R
但相应的,这样做速度就慢了下来。所以还得根据问题的规模来决定使用什么方案。
4 {; r: ]* b& O% Q& n7 a9 |4 }5 K$ u- N& E* R/ Q. w
总体来讲,对于可以条件判断较复杂,且根据前一个(不)符合条件的情况较简单的推出下一个(不)符合条件的情况,(不)符合条件的情况分布较稀疏的问题,用筛选法速度较快。如果第3题中加一个条件被2除余1,用筛选法就不太合算了。$ U, i' N- n# r- r+ H+ {
1 W8 U* E8 R5 M4 ~# h 最后说明一下,此次给出的程序目的在于说明方法,在效率并不是最高的 |
zan
|