- 在线时间
- 0 小时
- 最后登录
- 2004-7-22
- 注册时间
- 2004-5-28
- 听众数
- 1
- 收听数
- 0
- 能力
- 0 分
- 体力
- 124 点
- 威望
- 0 点
- 阅读权限
- 20
- 积分
- 43
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 4
- 主题
- 7
- 精华
- 0
- 分享
- 0
- 好友
- 0
升级   40% 该用户从未签到
 |
所谓筛选法就是从全集中将不合格的项全部删去,剩下的就是答案。
0 n! n6 }4 w' q# P! h) {4 l
& [3 Q1 ~- E c1: 求1-100之间的质数 w8 C% a3 H; F& R! Q. |) |
: x7 k& X: m' F- Q! ?- v m% \ 原理:先将2的倍数全部划掉,再将3的倍数全部划掉……直到将10的倍数全部划掉(10^2 = 100 )。剩下的就是质数.7 g& Y$ K/ ~* z9 H+ X% F
5 D$ I+ n4 V5 m5 B
void fun1()
' S8 i8 z; v; y8 U. Z{
2 n: e7 R- I2 o+ y int i, j;+ p+ `( `1 ~, P. H% \" T
bool flag[100];
6 j w! ^* e* r2 P
0 T# u" P# N6 u- h0 C for ( i = 2; i < 100; i++ )
" @' d! t! Y z6 I3 G, y- Z flag = true;
/ H& A$ @; I4 ^. S5 | F4 j4 H0 ^
! G6 R, Y2 @: e/ h //下面开始划掉合数6 a1 c9 P5 V( ~3 p
for ( i = 2; i < 10; i++ ) //因为合数的最小正因数不大于它的平方根3 x8 l4 `) y: q) ^! D
{
0 v4 w: S, R6 c$ H* S' G. ` if ( flag == false )
. F( h7 \- P: A& o$ C* ]: G continue; //既然i已经是合数,它的倍数应该已经被划掉0 I' D0 M0 S5 l; z: D
for ( j = 2; j * i < 100; j++ )//划掉i*j% h. L2 p9 X# [# M! a" |; a
flag[i*j] = false;# Q' W; @% X" c+ R3 ]3 L( s |4 a
}
/ q1 H5 R; s- U# o" D$ h: ^1 G( ?6 t+ H, |2 y/ q* t6 k# l, K! ?3 {" y
//输出结果
% I! u. V; `: Y, o; x0 j for ( i = 2; i < 100; i++ )( s4 p8 N4 g3 }4 H/ h
if ( flag )* w! k! R) X8 c. d7 E. {
cout << i << ' ';
9 G: D, D2 Z3 k}
7 E1 v5 U" s1 c# B- u, Y- X A* l' m$ O- [! ?& B
2: 30个人站成一圈,从第一个人开始报数,凡报到5的拉出去毙了,剩下的人接着从1开始报,直到只剩一人放掉。想活命该站哪?
. A/ w- S. ^/ E' ]% O- z5 e; r2 z7 s. h8 ~. ^; e+ N& y" [! r. D. @
这是个经典问题,解法就是模拟整个过程,有点类似于循环队列。
; P" S) O. F$ _1 R& T- I2 n3 {" ?# Z, ^% |6 s+ l
另外,为了程序上处理方便,可以假定所有的人都拉去毙了,然后看一下最后一个被毙掉的是谁。另一处为了处理方便而采取的措施是pos的初始值设为-1.很多时候,对问题的问法稍作变动,或者将初始值、加减变量的位置稍作调整,用程序处理起来会方便很多。
: @5 D! G( s, Z9 y3 g+ A% ]
$ B' V g- ? L! Q. F6 G$ C" @void fun2()0 j) H7 P6 l) u% l* Q
{
' j6 e1 ]* k- Z bool flag[30];//标记第i个人的状态,false已被毙掉,true还没被毙掉9 F( A6 I9 p1 [1 k4 K
% \; { j2 n9 L" o- K for ( int i=0; i< 30; i++ )
! M, ]; \8 k/ O# v) y1 ?$ \5 h$ i( C flag = true;+ U+ h! t1 O% l- }) J$ u! `
, V1 R3 t6 p" F* v h& K7 T
int n = 30;//还剩几个人
4 _* r( [/ }: d# I9 }% V9 f+ f) Q8 T int cnt;
' B) ?, a2 D# v) x int pos = -1;//初始值不一定从0开始,设为-1处理起来较方便. K% `8 e) [7 A C' X0 C- Q
while ( n > 0 )
0 `; ?7 c n) I$ c" a {" t. T: z- i+ L3 W- W5 b
cnt = 0;
9 y& O9 i# T/ F0 W while ( cnt < 5 )
) z, b) l2 s, p {
% b: o \' F8 k" f0 u if ( ++pos == 30 )
4 @) @& T. O0 i3 M pos = 0;% J, v6 O8 k. v! {# H5 o& p& m
if ( flag[pos] )//此人还没被毙掉
4 f5 P7 t; `/ i4 T4 g4 V cnt ++;* ]7 [- M# M; `( `/ d
}+ Y; l/ i) K* O5 a1 h2 |
//退出时cnt == 5,pos指向报5的人
2 A: Q$ ?& B$ l' _4 x2 z, v' @ flag[pos] = false;//毙掉: }2 t. C! V3 \* Y
n --;//剩余人数减1, c% r, x5 b) r! Z
}+ y8 p4 S: W' U7 a; P+ O1 v
//最后一个被毙的就是幸存者+ Z& R) G2 X- Z3 ^" A
//之所以加1是因为程序中从0开始计数,输出却以1开始计数# J" O; H% ?* i- }8 s$ N
cout << pos + 1 << ' ';
: R& A# _* R; u; V) B+ {! H}# G) T4 _) [# T. O
8 U5 V! B! ]. B1 L; H8 b3 c" v3: 一个数被5除余3,被7除余2,求此数最小为几。
4 C% m( ^" p; C; h% N" T7 g2 _3 Z. @) C, k5 c1 e! T" T$ |
筛选法不一定非要标记true/false,有时候也可以使用计数来进行筛选,这个问题就是一例。! Z% q- C" s/ t0 d
首先,如果问题有解,则解必小于 5 * 7 = 35,只用在此范围内筛选即可。
& S, M4 Z, R3 }5 M) T- | 在程序处理上,如果一个数满足一个条件,就将计数值加1,最后计数值为3的即为所求。
4 g+ w8 v+ z- b( T# D) P1 g4 g* J$ C$ ^1 A0 K8 T
void fun3()
* }& z- M4 I( U+ {{$ H9 d1 y; I4 X2 K: Q
int a[105];//105 = 5 * 7
) K0 f# A2 K: h( p int i;; \7 W. x* p p9 D; k, `6 `9 L( U: T* Q
//计数清0
U. m2 o% k; o6 c9 q# ^ for ( i = 0; i < 35; i++ )# l- G3 H8 d( y) `
a = 0;
9 s/ \7 |9 {' T4 o //开始筛选2 U/ @. a/ {: e) G" I5 b
for ( i = 3; i < 35; i += 5 )3 Y2 Z/ c$ g; _1 g, G
a ++;1 R8 }: R! g4 U( U" m; [( c4 `4 d) |7 b
for ( i = 2; i < 35; i += 7 ); H4 \; W: }: N$ l1 u
a ++;- i9 ?7 \1 L7 A% P3 W6 |- j
! |, s& _# `! p5 c9 f, t
for ( i = 0; i < 35; i++ )
- t1 O V! w6 ^ if ( a == 3 )9 d5 N; Z* J+ p5 z6 {, w
{" b2 x h" D+ N% v, n
cout << i << endl;
0 |0 B; y7 i, h0 k: g8 ?1 G# ? return;
/ l6 z8 m- \: {1 E8 C }
( G& K7 m. E4 G4 E //如果执行到这里说明无解- t: t/ k; K& r* r9 G
cout << "No Answer!" << endl;! ^0 |7 e* a# b$ _& t7 Y: o
}
' s0 c1 I# r, s# \ f, ^7 U) V4 Y/ ?9 [& h& A/ \4 Z+ e& V
9 |4 { F' D: V: j$ @" d8 f! m' T
总结:6 C, z/ ?& _# L3 B
筛选法的时间效率较高,但需要一个辅助数组,这就意味着对规模很大的问题不适用。例如第3个问题,条件多1个,需要的空间就翻几倍。解决的办法是:
, b, T9 m0 y J+ w% ~/ C
$ r0 V0 \8 F7 _5 Qfor ( int i = 0; i< n; i++ )# b) y" @" X. _' b
{4 f, I9 m$ u* [8 p" }
if ( i % 5 == 3 && i % 7 == 2 && ... )* T/ F3 ~/ @1 d8 e I% t
cout << i;
; S0 l8 g! S( V}
1 G! h. I: k' ^ 但相应的,这样做速度就慢了下来。所以还得根据问题的规模来决定使用什么方案。" e( o5 a( p( p# U
$ r+ S- |3 g* r& k# X 总体来讲,对于可以条件判断较复杂,且根据前一个(不)符合条件的情况较简单的推出下一个(不)符合条件的情况,(不)符合条件的情况分布较稀疏的问题,用筛选法速度较快。如果第3题中加一个条件被2除余1,用筛选法就不太合算了。
- `) h8 x7 N* O a% z7 O
$ X. L/ n, E2 q5 O4 t 最后说明一下,此次给出的程序目的在于说明方法,在效率并不是最高的 |
zan
|