- 在线时间
- 0 小时
- 最后登录
- 2004-7-22
- 注册时间
- 2004-5-28
- 听众数
- 1
- 收听数
- 0
- 能力
- 0 分
- 体力
- 124 点
- 威望
- 0 点
- 阅读权限
- 20
- 积分
- 43
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 4
- 主题
- 7
- 精华
- 0
- 分享
- 0
- 好友
- 0
升级   40% 该用户从未签到
 |
所谓筛选法就是从全集中将不合格的项全部删去,剩下的就是答案。1 g- L: N6 t( \) v! L7 x" v1 S2 }
' u7 q, Z. c1 n1: 求1-100之间的质数
) i s( E9 f5 n5 B% E6 t1 ]# E6 f2 f/ R& ^/ K
原理:先将2的倍数全部划掉,再将3的倍数全部划掉……直到将10的倍数全部划掉(10^2 = 100 )。剩下的就是质数.3 `9 ] C+ @6 h* z7 l$ T
! ~ }/ @6 p' @2 ovoid fun1()
: g: P& a) }, X; [4 E% l{! H1 J t' g. M. Y
int i, j;
$ x# C0 C" X: h7 `1 q Y5 p5 \ bool flag[100];
+ _" E7 A$ y0 a& [7 P6 f
0 q/ P f' Y2 B7 m% l! r! i( S for ( i = 2; i < 100; i++ )+ n" ~! `! E% O( i3 m9 ^& U
flag = true;7 V w7 t3 u* @+ F" U$ ?0 W
* K3 X& J$ k1 d! f
//下面开始划掉合数
2 }1 [0 m! |7 d& Z6 P9 Y for ( i = 2; i < 10; i++ ) //因为合数的最小正因数不大于它的平方根
$ h7 F" |8 |, T# k {
; E2 D. O- B$ }, i: s if ( flag == false )3 d! I6 l2 f/ \' K: d, ~% }
continue; //既然i已经是合数,它的倍数应该已经被划掉! Q% h4 |' m* S0 N; O9 z6 N# V- f" v" X
for ( j = 2; j * i < 100; j++ )//划掉i*j
8 {# I7 V% Y, N- w' l m/ I flag[i*j] = false;
. U6 V" K. m: L# q, H- t. } }6 J8 O, J+ \3 u" ]9 H) \- s
1 k0 a4 ^6 L6 J, D2 c( n //输出结果1 q5 ~3 c$ M; k. o' R4 U2 Z* q8 k5 {
for ( i = 2; i < 100; i++ )
# J) _/ d2 w/ J) {: w5 z" e if ( flag )+ ? Q3 S6 q, N8 ]* j6 k
cout << i << ' ';: R1 i% u; L1 D% h1 T$ ^7 M8 `
}
+ \, M6 {" z. Q' U( Q9 Z$ y0 Q: l# Y! Z2 S0 M- l: V( o' e& Z; J; M: U
2: 30个人站成一圈,从第一个人开始报数,凡报到5的拉出去毙了,剩下的人接着从1开始报,直到只剩一人放掉。想活命该站哪?" p$ P- Z; _) [+ q1 m4 s
; Z5 l# W% K1 \) I0 |+ s 这是个经典问题,解法就是模拟整个过程,有点类似于循环队列。" |/ Q( e5 @7 ], X5 Y* y
' T$ c3 I' d ]) e" J, O0 K7 ?. [
另外,为了程序上处理方便,可以假定所有的人都拉去毙了,然后看一下最后一个被毙掉的是谁。另一处为了处理方便而采取的措施是pos的初始值设为-1.很多时候,对问题的问法稍作变动,或者将初始值、加减变量的位置稍作调整,用程序处理起来会方便很多。
5 R1 z$ |8 D, D) c8 E; o) j! v: A' F' c8 S5 H' B, ]
void fun2()7 ?! ~1 a$ r* f
{
9 k& n2 W# u( z/ p4 C: C bool flag[30];//标记第i个人的状态,false已被毙掉,true还没被毙掉3 {# y. H5 y% y$ v& i- l
! J" \8 n! P: a
for ( int i=0; i< 30; i++ )
. N J7 r& N% W1 \ J( U flag = true;: i8 O, |, l9 H
8 i& z$ a; y- o( o int n = 30;//还剩几个人
9 w4 U- Y0 c5 i) R1 y3 N int cnt;( A# ^9 Q" [9 _0 @9 U
int pos = -1;//初始值不一定从0开始,设为-1处理起来较方便
& Q* G% }! G( {) V3 ^ while ( n > 0 )
& i& y! T$ V4 @' w9 e8 O {
' I* y4 y3 U/ Y& W cnt = 0;
0 E) w7 q) l1 G7 Y while ( cnt < 5 )# S- H0 ]4 A! R" H& V5 B0 G
{
% A3 a: P' {: X) k( r, V* i( L if ( ++pos == 30 )2 V2 q9 }, K4 n) V6 f0 z
pos = 0;
' {: K* R, p6 A! a# R1 S, B if ( flag[pos] )//此人还没被毙掉
3 s) }. Y0 a/ {4 c5 D* K cnt ++;6 u1 |8 t" ^! G7 C- p" ?' c6 \
}
; d3 F8 R# j+ p4 `" F7 f* K0 m$ J //退出时cnt == 5,pos指向报5的人
( P$ m) u! B- r$ J5 L/ \ flag[pos] = false;//毙掉+ }3 P# W& `. Y5 ~- i+ Z) J
n --;//剩余人数减12 N7 v; C4 P; l! A! [0 f
}
- G% q. O, {: p& G x& c: E) L //最后一个被毙的就是幸存者 A$ t1 z+ k, Y: `/ a
//之所以加1是因为程序中从0开始计数,输出却以1开始计数
1 `4 ~0 W3 |% X; F+ i cout << pos + 1 << ' ';3 P `. z+ Q# ]6 W8 P/ |2 a% h& d% E
}
u8 K& {7 b4 d! V( o
1 s! P# T; ]: K N1 n4 k: q3: 一个数被5除余3,被7除余2,求此数最小为几。
$ U& {7 p% s7 G2 q
5 I+ z: }6 w# h- r+ K) Y" N6 e 筛选法不一定非要标记true/false,有时候也可以使用计数来进行筛选,这个问题就是一例。
1 ~( U+ |% A3 j 首先,如果问题有解,则解必小于 5 * 7 = 35,只用在此范围内筛选即可。7 m3 f3 j; ]( X, [7 k" E
在程序处理上,如果一个数满足一个条件,就将计数值加1,最后计数值为3的即为所求。
4 }6 U# v8 v2 V- S4 U N( G. H5 i1 ~/ F
void fun3() t2 Q/ d) ]' P% l) |
{: a5 `. @5 j$ l7 t1 B' r8 Y8 W- U
int a[105];//105 = 5 * 7
& @: K$ d+ W8 K/ _/ ? j int i;8 t* s7 k5 j% U8 u, s3 O4 P+ v
//计数清02 }" N' _4 _( H/ f D: P& g; A
for ( i = 0; i < 35; i++ )
4 x( ]4 Y$ m. `# r% U a = 0;" @$ @6 |* a9 P* L; d2 L* E' P
//开始筛选
h: u. {0 u/ e/ _: _ for ( i = 3; i < 35; i += 5 )
9 {" P1 V1 Z2 I3 ~ a ++;
2 m7 v, @; d% z* M# @9 q J for ( i = 2; i < 35; i += 7 )* U- l0 `+ O: v+ ^: n+ N/ {
a ++;
* ?6 l f& O' c9 y' r* ?% O I+ ?* \ Y
for ( i = 0; i < 35; i++ )
4 q: P, `6 H% H& o if ( a == 3 )+ r# {2 K& B; H* E' g
{
$ u- U1 X7 u! x' X1 z0 u cout << i << endl;# p' ]3 ^1 g/ U/ U$ m& f# f
return;
" P' a% {+ K0 m; A6 r; S* p }9 r1 r) U1 b5 N6 e8 E, y
//如果执行到这里说明无解
: V% ~' C5 d3 m. Q) a7 O+ B* X cout << "No Answer!" << endl;
1 b+ Q. ?! v2 M1 N2 S}
; M& ?0 w. o1 z+ H) [# x" ]# l8 |
/ p2 R3 C. e0 P: ~# Q" U+ ~+ |总结:
4 i2 R% J% T0 Q5 \0 X+ S 筛选法的时间效率较高,但需要一个辅助数组,这就意味着对规模很大的问题不适用。例如第3个问题,条件多1个,需要的空间就翻几倍。解决的办法是:
7 u% M4 F- G- D. d+ k
+ Q8 ~: Z* U; z5 pfor ( int i = 0; i< n; i++ )
: C) R) t8 w2 g U$ t{1 L% ~: X1 `8 h- ~+ Q5 l
if ( i % 5 == 3 && i % 7 == 2 && ... )
$ g: B' w/ j) A3 R cout << i;! k( \) j+ I4 h5 i0 m+ P z
}1 l- R4 N$ s' a+ P' |0 p
但相应的,这样做速度就慢了下来。所以还得根据问题的规模来决定使用什么方案。
8 e' t: p( B( g5 h6 H% [8 S; y$ p( y I3 b" t: x: U& j r
总体来讲,对于可以条件判断较复杂,且根据前一个(不)符合条件的情况较简单的推出下一个(不)符合条件的情况,(不)符合条件的情况分布较稀疏的问题,用筛选法速度较快。如果第3题中加一个条件被2除余1,用筛选法就不太合算了。
* Q1 X5 N( A. o w' R, h% g `
8 L8 p }3 Y* O" F7 K: n* y9 z' v 最后说明一下,此次给出的程序目的在于说明方法,在效率并不是最高的 |
zan
|