- 在线时间
- 0 小时
- 最后登录
- 2004-7-22
- 注册时间
- 2004-5-28
- 听众数
- 1
- 收听数
- 0
- 能力
- 0 分
- 体力
- 124 点
- 威望
- 0 点
- 阅读权限
- 20
- 积分
- 43
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 4
- 主题
- 7
- 精华
- 0
- 分享
- 0
- 好友
- 0
升级   40% 该用户从未签到
 |
所谓筛选法就是从全集中将不合格的项全部删去,剩下的就是答案。
1 i7 m" ]9 g+ J" {
. w2 N3 L4 Y/ q$ G1: 求1-100之间的质数, ]6 x" K: I" [3 u K" k
6 Y& `8 g, Z9 h 原理:先将2的倍数全部划掉,再将3的倍数全部划掉……直到将10的倍数全部划掉(10^2 = 100 )。剩下的就是质数.
$ V$ A! W7 {( V. T9 Q6 X @1 z' B& R. J6 j* m" q2 L& Y
void fun1()
2 b; c4 \6 u% x1 s% A5 L{
% j, B1 O) R$ g, f4 R. C0 \+ g9 p int i, j;
?2 h/ `$ R# z bool flag[100];( g8 E# b( L* E& V# K
7 U6 V) D- q8 c9 b for ( i = 2; i < 100; i++ )0 [2 q; T2 g1 s8 y
flag = true;( `" c6 E- v' c* ~
, C( I* u8 o; B0 w$ a. u. | H# Q
//下面开始划掉合数
5 f) y. u0 E, w8 p$ x8 ] for ( i = 2; i < 10; i++ ) //因为合数的最小正因数不大于它的平方根2 t; }) f! u M+ }
{8 i/ h4 q6 [. B( O1 Q
if ( flag == false )
( W5 h) w9 h) Z continue; //既然i已经是合数,它的倍数应该已经被划掉9 p. a( C0 ^4 i* b& J1 Z& P+ O
for ( j = 2; j * i < 100; j++ )//划掉i*j. c6 C. I& g) O/ I. k' i2 @9 c
flag[i*j] = false;5 @+ O+ T+ H7 X5 d: W
}
: j( f! l3 U( x' x8 s2 {# E# j, N) H! ^/ n
//输出结果! t: R0 k. G+ M- @* F% x
for ( i = 2; i < 100; i++ )% `" I) U9 U1 p- G" J: N( G
if ( flag )
6 ?, w8 e$ y5 b1 s1 ]/ H cout << i << ' ';
' E$ I4 f# l0 D5 D, k5 E3 i}7 R# y. p% N3 w* g3 S; P( S
9 a9 J' K- m: j6 \
2: 30个人站成一圈,从第一个人开始报数,凡报到5的拉出去毙了,剩下的人接着从1开始报,直到只剩一人放掉。想活命该站哪?
# G; G! c2 N3 s! i0 z. q7 m8 w! a/ o% \8 M' X' J/ I& N: @
这是个经典问题,解法就是模拟整个过程,有点类似于循环队列。$ B9 j4 V/ E* F: z3 G) p% I5 x0 E
6 a& o0 k) k# @1 e/ @ 另外,为了程序上处理方便,可以假定所有的人都拉去毙了,然后看一下最后一个被毙掉的是谁。另一处为了处理方便而采取的措施是pos的初始值设为-1.很多时候,对问题的问法稍作变动,或者将初始值、加减变量的位置稍作调整,用程序处理起来会方便很多。% b s" x* k3 S; P3 F
& e2 ^/ G( p3 p" ^% yvoid fun2()3 m/ Q4 Y* t. e. B/ ]2 [
{1 m! J* W0 g) h% w" ?
bool flag[30];//标记第i个人的状态,false已被毙掉,true还没被毙掉
. ^5 g4 s* ?0 e3 N- a* q# n; @& Z3 @$ ~% y9 \
for ( int i=0; i< 30; i++ )
" w6 N: Z! m7 G) o \% U, M8 r flag = true;
. v5 T5 G' y- k# C0 i
8 ?( I6 n4 ~; w$ F" ^7 x! L/ c/ \+ z int n = 30;//还剩几个人
# M- S9 a% Z0 k/ G% Z int cnt;
- F4 x6 _7 ]7 X3 b# U int pos = -1;//初始值不一定从0开始,设为-1处理起来较方便
6 q" R. L. i7 R while ( n > 0 )( f0 Y9 z/ |/ V2 {- U
{/ u4 g7 n2 j$ Q
cnt = 0;
0 j& A2 d7 D! u2 s8 L. ^. S while ( cnt < 5 )
8 o7 h$ R4 p! |# s' _ {
6 u' T! y) @ J& Z4 ^4 Y0 Z if ( ++pos == 30 ), }/ B; [1 g0 G9 u
pos = 0;3 Q$ v4 j6 a' k: N, G6 K
if ( flag[pos] )//此人还没被毙掉
2 U3 u7 ]. H, r3 E cnt ++;
2 W2 O" N& [" M% x5 F! k6 \+ [ }
) ?# ^: I0 l0 |3 }: M //退出时cnt == 5,pos指向报5的人
+ v* f2 W1 Z+ Q- l flag[pos] = false;//毙掉, i6 l7 f( L: f! }
n --;//剩余人数减1$ Z; R& K; E' }. V$ S* \4 U
}
6 r* D0 g3 H& G) g6 Y: g2 C( X2 N //最后一个被毙的就是幸存者+ h, R8 _& f, q4 S
//之所以加1是因为程序中从0开始计数,输出却以1开始计数% K. B4 i9 n5 N+ }+ W9 {9 a1 s
cout << pos + 1 << ' ';
* R0 C) v0 J6 d& Y5 G}3 w7 _4 A" q) i1 @; j
- s/ _6 ?* {" P- o) H3: 一个数被5除余3,被7除余2,求此数最小为几。
6 c$ M8 O1 Y! M6 E9 S8 ^0 Y. h
' u, K! c# r% Y4 {8 O) w1 N& @ 筛选法不一定非要标记true/false,有时候也可以使用计数来进行筛选,这个问题就是一例。/ p0 u! [6 f! O* t- n/ k
首先,如果问题有解,则解必小于 5 * 7 = 35,只用在此范围内筛选即可。" A+ Q2 P7 |% D' {: K+ b3 ~
在程序处理上,如果一个数满足一个条件,就将计数值加1,最后计数值为3的即为所求。: D7 M: ~0 ]* ~' y; K
3 ^" `" e+ L0 k" Z4 l% W) g9 _void fun3()1 H* j8 m/ P/ \. d: _1 p
{
5 Z, D9 f* \% a" F int a[105];//105 = 5 * 7
* Q) h- P" _# N. P5 C- o6 s. X int i;/ l8 Z$ F: F! t5 V4 Z" ~
//计数清0
$ W5 Z' D' P9 C( i, W, l for ( i = 0; i < 35; i++ )
6 U6 o% ^5 k) O a = 0;
, r8 P0 n1 p7 F. P9 D //开始筛选
! a2 g/ L+ ~, F _ for ( i = 3; i < 35; i += 5 )# J) Y$ W6 L' h. D8 W" H
a ++;
2 `5 ]! K4 @, K X% S for ( i = 2; i < 35; i += 7 )1 l: P6 {7 C2 d7 M
a ++;
9 b' s4 g- V* l, n
) a; Z/ [ [9 ?, v for ( i = 0; i < 35; i++ )
7 K# D% x5 l H2 y" K$ {3 f w! t" G if ( a == 3 )0 }* o* `3 D: x4 ~3 R
{: _( X1 W9 X1 V) X
cout << i << endl;
: ^7 a* l* j: e4 K0 _" ?5 D5 ] return;
+ \* A) b2 f5 x3 e/ d8 a- m; Y }4 F/ h1 H; `; @; e6 C# ?- T
//如果执行到这里说明无解
& ?3 f6 X' C% w8 ]4 Z# x. e cout << "No Answer!" << endl;' v: z8 i' ]8 W- F& J1 I Z
}
0 w& N [" f/ y2 `! C$ C% ?1 {1 x8 s7 q& g7 }5 K7 H- x
; P* j6 T* a, Y& I- y- u, b
总结:/ X; \ D2 @& F$ n( s) m( b
筛选法的时间效率较高,但需要一个辅助数组,这就意味着对规模很大的问题不适用。例如第3个问题,条件多1个,需要的空间就翻几倍。解决的办法是:
0 D p4 A) k0 Y& _2 E
1 i# V% L, y N- nfor ( int i = 0; i< n; i++ ) t& s( z4 Y u. x4 y
{
6 `$ b6 c/ ^, O! k if ( i % 5 == 3 && i % 7 == 2 && ... )0 D4 R1 f" P) ?/ n
cout << i;
B" ^5 T! s6 v# I. `9 {}# p) o- b7 K1 M8 ^( P d
但相应的,这样做速度就慢了下来。所以还得根据问题的规模来决定使用什么方案。
7 [6 p% G* k1 k% C" P1 a5 {" e _: T3 V2 M6 x1 F
总体来讲,对于可以条件判断较复杂,且根据前一个(不)符合条件的情况较简单的推出下一个(不)符合条件的情况,(不)符合条件的情况分布较稀疏的问题,用筛选法速度较快。如果第3题中加一个条件被2除余1,用筛选法就不太合算了。
$ O9 G ^7 a) U- I: P, o
( ^/ ~, t# F, g1 i8 ~ 最后说明一下,此次给出的程序目的在于说明方法,在效率并不是最高的 |
zan
|