- 注册时间
- 2004-8-29
- 最后登录
- 1970-1-1
|

楼主 |
发表于 2005-8-27 12:54:00
|
显示全部楼层
- §6.2 关于运用贪心策略求解NPC类问题的讨论
- 正如前面所讲的那样,在南非举行的第九届国际奥林匹克信息学竞赛中首次引入了NPC类问题,在杭州举行的NOI98中引入了NOI发展史上的第一道NPC类问题--并行计算。可以说,NPC类问题正在日益引起人们的兴趣。它要求选手根据题意自己建立适当的模型,使程序的解尽量逼近最优解。目前,信息学竞赛所涉及到的少量NPC类问题主要是运用贪心策略或随机化算法去求较优解的。但是对于同一道NPC类问题来说,运用不同的贪心选择所求得的最优解是不同的,不同的贪心选择针对不同的测试数据所得解与最优解的逼近程度也是不同的。所以有关NPC类问题的众多特性以及哪些问题运用贪心策略求得的较优解逼近于最优解仍是需要我们花费大量精力去研究的。信息学奥林匹克的精华-激励创新也许在求解NPC类问题时会得到最大程度的体现。
- 七、 总结
- 通过对贪心策略的分析,大家可以看出:贪心策略作为一种高效算法,广泛地应用与信息学奥林匹克竞赛中。即使表面上看起来与贪心策略关系甚微的题目,运用贪心算法也可使程序的运行效率大大提高。因此,深刻理解贪心策略的数学模型、特点、理论基础、尤其是运用其基本思想解决具体问题是十分重要的。希望本文能给参赛选手以一定的启发。
- 【附 录】
- 【参考书目】
- 1 《实用算法的分析与程序设计》
- 吴文虎,王健德编著,电子工业出版社,ISBN 7-5053-4402-1
- 2 《计算机算法导引》
- 卢开澄编著,清华大学出版社,ISBN 7-302-02277-1
- 3、 《国际大学生程序设计竞赛试题解析》
- 王建德,柴晓路编著,复旦大学出饭社 ISBN 7-309-02141-X/T·210
- 【部分试题及源程序】
- 1、 吉尔的又一个乘车问题:
- Input file:jill.in
- Jill likes to ride her bicycle, but since the pretty city of Greenhills where she lives has grown, Jill often uses the excellent public bus system for part of her journey. She has a folding bicycle which she carries with her when she uses the bus for the first part of her trip. She follows the bus route until she reaches her destination of she comes to a part of the city she does not like. In the latter event she will board the bus to finish her trip.
- Through years of experience, Jill has rated each road on an integer scale of "niceness". Positive niceness values indicate roads Jill likes; negative values are used for roads she does not like. Jill plans where to leave the bus and start bicycling, as well as where to stop bicycling and re-join the bus, so that the sum of niceness values of the roads she bicycles on is maximized. This means that she will sometimes cycle along a road she does not like, provided that it joins up two other parts of her journey involving roads she likes enough to compensate. It may be that no part of the route if suitable for cycling so that Jill takes the bus for its entire route. Conversely, it may be that the whole route is so nice Jill will not use the bus at all.
- Since there are many different bus routes, each with several stops at which Jill could leave or enter the bus, she feels that a computer program could help her identify the best part to cycle for each bus route.
- INPUT
- The input file contains information on several bus routes. The first line of the file is a single integer b representing the number of route descriptions in the file. The identifier for each route (r) is the sequence number within the data files,1≤r≤b. Each route description begins with the number of stops on the route : an integer s, 2≤s≤20,000 on a line by itself. The number of stops is followed by s-1 lines, each line i(1≤i≤s) is an integer ni representing Jill's assessment of the niceness of the road between the two stops i and i+1.
- OUTPUT
- For each route r in the input file, your program should identify the beginning bus stop i and the ending bus stop j that identify the segment of the route which yields the maximal sum of niceness m=ni+ni+1+…+nj-1.If more than one segment is maximally nice, choose the one with longest cycle ride(largest j-i). To break ties in longest maximal segments, choose the segment that begins with the earliest stop(lowest i).For each route r in the input file, print a line in the form:
- The nicest part of route r is between stops i AND j.
- However, if the maximal sum is not positive, your program should print:
- Route r has no nice parts.
- INPUT SAMPLE
- 3
- 3
- - 1
- 6
- 10
- 4
- 5
- 4
- 3
- 4
- 4
- 4
- 4
- - 5
- 4
- 2
- 3
- 4
- OUTPUT SAMPLE
- The nicest part of route 1 is between stops 2 and 3
- The nicest part of route 2 if between stops 3 and 9
- Route 3 has no nice parts
- 2、求最长路径问题(NOI93):
- 对一个不存在回路的有向图,编程求出途经结点数最多的一条路径。有向图存放在一个文本文件中,第0行为一个数字,为该图的结点总数N,其下还有N行,每行有N个非0即1的数字。若第i行第j列的数字为1,则表示结点i到结点j存在由i指向j的边,否则该数为0。
- 3、删数问题的源程序:
- 输入数据:一个高精度正整数N,所删除的数字个数S。
- 输出数据:去掉的数字的位置和组成的新的正整数。
- Program Delete_digit;
- Var n:string;{n是由键盘输入的高精度正整数}
- s,a,b,c:byte;{s是所要删除的数字的个数}
- data:array[1..200] of 0..9; {记录删除的数字所在位置}
- begin
- readln(n);
- readln(s);
- for a:=1 to s do
- for b:=1 to length(n) do if n[ b]>n[b+1] then {贪心选择}
- begin
- delete(n,b,1);
- data[a]:=b+a-1; {记录所删除的数字的位置}
- break;
- end;
- while n[1]='0' do delete(n,1,1); {将字符串首的若干个"0"去掉}
- writeln(n);
- for a:=1 to s do writeln(data[a],' ');
- end.
- 4、最优乘车问题
- 输入数据:输入文件INPUT.TXT。文件的第行是一个数字M(1≤M≤100)表示开通了M条单向巴士线路,第2行是一个数字N(1<N≤500),表示共有N个车站。从第3行到第M+2行依次给出了第一条到第M条巴士线路的信息。其中第i+2行给出的是第i条巴士线路的信息,从左至右依次按行行驶顺序给出了该线路上的所有站点,相邻两个站号之间用一个空格隔开。
- 输出数据:输出文件是OUTPUT.TXT。文件只有一行,为最少换车次数(在0,1,…,M-1中取值),0表示不需换车即可达到。如果无法乘车达到S公园,则输出"NO"。
- Program Travel;
- var m:1..100; {m为开通的单向巴士线路数}
- n:1..500; {n为车站总数}
- result:array[1..501] of -1..100; {到某车站的最少换车数}
- num:array[1..500,1..50] of 1..500; {从某车站可达的所有车站序列}
- sum:array[1..500] of 0..50; {从某车站可达的车站总数}
- check:array[1..500] of Boolean; {某车站是否已扩展完}
- Procedure Init;
- var f1:text;
- a,b,c,d:byte;
- data:array[1..100] of 0..100;
- begin
- assign(f1,'input.txt');
- reset(f1);
- readln(f1,m);
- readln(f1,n);
- result[501]:=100;
- for a:=1 to m do
- begin
- for b:=1 to 100 do data[ b]:=0;
- b:=0;
- repeat
- inc(b);
- read(f1,data[ b]);
- until eoln(f1);
- for c:=1 to b-1 do
- for d:=c+1 to b do
- begin
- inc(sum[data[c]]);
- num[data[c],sum[data[c]]]:=data[d];
- end;
- end;
- end;
- Procedure Done;
- var min,a,b,c,total:integer;
- begin
- fillchar(result,sizeof(result),-1);
- result[1]:=0;
- for c:=1 to sum[1] do result[num[1,c]]:=0;
- b:=data[1,1];
- repeat
- for c:=1 to sum[ b] do
- if (result[num[b,c]]=-1) then result[num[b,c]]:=result[ b]+1;
- min:=501;
- for c:=1 to n do if (result[c]<>-1) and (result[c]<result[min])
- then min:=c;
- b:=min;
- until result[n]<>-1;
- writeln(result[n]);{到达S公园的最少换车次数}
- end;
- begin
- Init;
- end.
- 5、最佳游览路线问题
- 输入数据:输入文件是INPUT.TXT。文件的第一行是两个整数M和N,之间用一个空格符隔开,M表示有多少条旅游街(1≤M≤100),N表示有多少条林荫道(1≤N≤20000)。接下里的M行依次给出了由北向南每条旅游街的分值信息。每行有N-1个整数,依次表示了自西向东旅游街每一小段的分值。同一行相邻两个数之间用一个空格隔开。
- 输出文件:输出文件是 OUTPUT.TXT。文件只有一行,是一个整数,表示你的程序找到的最佳浏览路线的总分值。
- Program Tour;
- var m,n:integer; {M为旅游街数,N为林荫道数}
- data:array[1..20000] of -100..100;{data是由相邻两条林荫道所分}
- procedure Init; {隔的旅游街的最大分值}
- var a,b,c:integer;
- f1:text;
- begin
- assign(f1,'input.txt');
- reset(f1);
- read(f1,m,n);
- for a:=1 to n-1 do read(f1,data[a]); {读取每一段旅游街的分值}
- for a:=2 to m do
- for b:=1 to n-1 do
- begin
- read(f1,c);
- if c>data[ b] then data[ b]:=c; {读取每一段旅游街的分值,并选择}
- end; {到目前位置所在列的最大分值记入数组data}
- close(f1);
- end;
- procedure Done;
- var a,sum,result,c:integer;
- f2:text;
- begin
- result:=0;
- sum:=0;
- a:=0;
- while (a<n) do
- begin
- inc(a); {从数组的第一个数据开始累加,将累加所}
- sum:=sum+data[a]; {得到的最大分值记入result}
- if sum>result then result:=sum;
- if sum<0 then sum:=0; {若当前累加值为负数,则从当前状态起从新}
- end; {累加}
- assign(f2,'output.txt');
- rewrite(f2);
- writeln(f2,result);
- close(f2);
- end;
- begin
- Init;
- Done;
- end.
复制代码
|
|