[工学]poj搜索题总结.doc

上传人:sccc 文档编号:4532059 上传时间:2023-04-26 格式:DOC 页数:31 大小:161.50KB
返回 下载 相关 举报
[工学]poj搜索题总结.doc_第1页
第1页 / 共31页
[工学]poj搜索题总结.doc_第2页
第2页 / 共31页
[工学]poj搜索题总结.doc_第3页
第3页 / 共31页
[工学]poj搜索题总结.doc_第4页
第4页 / 共31页
[工学]poj搜索题总结.doc_第5页
第5页 / 共31页
点击查看更多>>
资源描述

《[工学]poj搜索题总结.doc》由会员分享,可在线阅读,更多相关《[工学]poj搜索题总结.doc(31页珍藏版)》请在三一办公上搜索。

1、poj搜索题总结初期篇 简单搜索(1)深度优先搜索 (poj2488,poj3009,poj1321)(2)广度优先搜索 (poj3278,poj1426,poj3126,poj3087.poj3414,poj2251,poj3083)(3)简单搜索技巧和剪枝(poj2531,poj1416,poj2676,1129) 看到这些题是不是很眼熟。没错,这就是某位大牛推荐初期要做的题。而这文章就是为这些题加上解题报告以及一些总结。 深度优先搜索poj2488:A Knights Journey 如果没有按字典序输出这个要求的话,就是简单的DFS,但是加上的话,就是麻烦题。这就要求求出全部的走法或在

2、行走时,按照某种顺序走。从时间上来说,当然是选择第二种了。若存在可行路线,则每个格子必然都走过。所以从A1开始,按照某种顺序走,若有解,则为所求,若无,则无解。/WA了N次,才发现是倒在字典序的手下/虽然题目没说,但是这道题最后一组数据后是没有空行的.否则会PE./若存在可行路线,则每个格子都走过。所以从(0,0)开始即可,不需要遍历每一个起始点/注意行走的方法(即MOV数组元素的排列),可以在找到可行解时,就使得其字典序最小 #include#include#include using namespace std; bool flag;string answer30;int chess303

3、0; /这个的设置一定要与下面的转换相对应,之前就是不对应,错了N次int mov82=-1,-2,1,-2,-2,-1,2,-1,-2,1,2,1,-1,2,1,2; string GetPosition(int x,int y) /将X,Y坐标转换成题目要求的形式 string stmp; stmp+=(char)(y+A); /由于先出现的是Y坐标(如B3),所以MOV数组中的Y应从-2到2的顺序变化 stmp+=(char)(x+1); return stmp; void SaveIt(int p,int q) /保存下答案 for(int i=0;ip;+i) for(int j=0

4、;jq;+j) answerchessij=GetPosition(i,j); void dfs(int p,int q,int num,int x,int y) if( num=p*q ) flag=true; SaveIt(p,q); return; int xx,yy; for(int i=0;i=0 & xx=0 & yycases; while( cases- ) cinpq; flag=false; memset(chess,0,sizeof(chess); chess00=1; dfs(p,q,1,0,0); /output coutScenario #count+:endl;

5、if( flag ) for(i=1;i=p*q;+i) coutansweri; coutendl; else coutimpossibleendl; if( cases!=0 ) coutendl; return 0; poj1321:棋盘问题这题是简单的DFS,但题目有个地方说得不是很清楚,就是以“#”为标志的位置才能放棋子。/一次AC,用了DFS,以递归回溯的形式实现题目说得有点不清楚,以“#”为标志的位置才能入棋子 #include#include using namespace std; int count;int chess88; /能放棋子为1,不能为0,放下棋子的是2 boo

6、l IsLegal(int x,int y) /由于一行只放一个,所以不用判断是否同行,这里只判断是否同列 for(int i=0;ix;+i) if( chessiy=2 ) return false; return true; void dfs(int n,int k,int num,int start) /num表示当前放了几颗棋子,START表示放棋子的超始行数 if( num=k ) +count; return ; for(int i=start;in;+i) for(int j=0;jnk & n!=-1 ) memset(chess,0,sizeof(chess); for(i

7、nt i=0;in;+i) /get input for(int j=0;jctmp; if( ctmp=# ) chessij=1; count=0; dfs(n,k,0,0); coutcountendl; return 0; 广度优先搜索DFS一般是用来求全部解。但可以使其按照某种方式前进而达到求最优解的目的。而BFS则常用于求最优解,但其缺陷是空间要求过大。用BFS还有一个易错点,就是队列空间申请得过小(特别是用循环数组),导致有一些情况判断来不及判断就被覆盖掉。POJ 1321: Catch That Cow这题如果是用循环数组做的话,一定要注意我说的那个易错点。 /做BFS的第一题

8、(用了类,STL中的队列),写完后,提交,TLE = =不用STL中的队列再加上剪枝后,就不TLE了,但一直RE = =(数组越界)不RE,然后又WA,发现这情况:0 100000 不能判断因为队列数组开得太小了,把还没来得及处理的数据给覆盖掉了改大后,才AC掉,阴险题#include/#include using namespace std; const int QMAX=50000; class NODE public: NODE(int xx=0,int ss=0):x(xx),step(ss) int x; int step; bool walk200001; /数组一定要足够大,否则

9、RENODE qQMAX; /队列int move32= 1,1,1,-1,2,0 ; /移动的方法 int main() / ifstream cin(test.in); int s,t,now,total,itmp; while( cinst ) now=0; total=1; memset(walk,0,sizeof(walk); /BFS qnow=NODE(s,0); walks=true; while( now!=total ) if( qnow%QMAX.x=t ) coutqnow%QMAX.stependl; break; for(int i=0;i3;+i) itmp=(q

10、now%QMAX.x*movei0)+movei1; if( itmp=0 & !walkitmp ) /先判断ITMP范围,否则RE walkitmp=true; q(total+)%QMAX=NODE(itmp,qnow%QMAX.step+1); +now; return 0; POJ 1426:Find The Multiple#include#include/#include using namespace std; const int QMAX=10000; /定义队列最大长度 bool IsMultiple(string str,int n) /判断STR能否被N整除 int l

11、en,mul,itmp; mul=10; itmp=0; len=str.size(); for(int i=0;ilen;+i) itmp=itmp*mul+(stri-0); if( itmpn & n!=0 ) now=0; total=1; /bfs qnow=1; while( now!=total ) if( IsMultiple(qnow%QMAX,n) ) coutqnow%QMAXendl; break; for(int i=0;i2;+i) q(total+)%QMAX=qnow%QMAX+letteri; +now; return 0; POJ 3126 Prime Pa

12、th也可以说是简单的BFS题。但有一点是注意的是SQRT函数可是被重载过。使用时,一定要指明其类型。BFS题,先求出全部四位的素数,然后再逐个尝试提交后CE,原来是SQRT函数作怪然后是WA,原因是素数判断错误,应该是J=SQRT(I),而不是JSQRT(I)修改后AC #include#include/#include using namespace std; class NODE public: NODE(int nn=0,int ss=0):num(nn),step(ss) int num; int step; const int PMAX=2000;const int QMAX=900

13、0;int primePMAX;bool selectPMAX;NODE qQMAX; void init(int& len) /算出全部的素数 bool flag; for(int i=1000;i9999;+i) flag=true; for(int j=2;j1 ) return false; num1/=10; num2/=10; return true; int main() / ifstream cin(test.in); bool flag; int cases,n,m,len(0),now,total; init(len); cincases; while( cases- )

14、cinnm; memset(select,0,sizeof(select); /bfs now=0; total=1; flag=false; qnow=NODE(n,0); while( now!=total ) if( qnow%QMAX.num=m ) coutqnow%QMAX.stependl; flag=true; break; for(int i=0;ilen;+i) if( !selecti & IsLegal(qnow%QMAX.num,primei) ) q(total+)%QMAX=NODE(primei,qnow%QMAX.step+1); selecti=true;

15、+now; if( !flag ) coutImpossibleendl; return 0; POJ 3414:Pots相比起之前的BFS题,不同点就只有输出路径。这时只要在类中多加一个变量来记录上一步是哪个步骤。但要注意,不要用循环数组,因为会把前面的一些值给覆盖掉。/bfs,简单题,注意怎样回溯出使用了哪些步骤就可以了/第一次WA,不能过的数据:91 100 95 答案是170/错误原因:walk数组开小了,导致有一些情况不能判断/从100X100改为201X201后就AC了#include#include#include#include using namespace std; con

16、st int QMAX=9000; class NODE public: NODE(int x1=0,int x2=0,int x3=0,int x4=0):a(x1),b(x2),method(x3),pre(x4) int a; int b; int method; /记录是用什么方法得到这步 int pre; /记录前一个步骤是哪个(数组的下标),回溯时用到; NODE qQMAX; /队列数组开大点,不要用循环数组bool walk201201; /注意最大应该是200,就是这里开小了,导致WAstring str7= ,FILL(1),FILL(2),DROP(1),DROP(2),

17、POUR(1,2),POUR(2,1) ; int main() ifstream cin(test.in); bool flag; int a,b,c,now,total,count; while( cinabc ) memset(walk,0,sizeof(walk); now=0; total=1; flag=false; walk00=true; qnow=NODE(0,0,0,0); while( now!=total ) if( qnow.a=c | qnow.b=c ) flag=true; break; /fill if( qnow.a!=a & !walkaqnow.b) /

18、method=1 means FILL(1) qtotal+=NODE(a,qnow.b,1,now); walkaqnow.b=true; if( qnow.b!=b & !walkqnow.ab ) /method=2 means FILL(2) qtotal+=NODE(qnow.a,b,2,now); walkqnow.ab=true; /drop if( qnow.a!=0 & !walk0qnow.b) /method=3 means DROP(1) qtotal+=NODE(0,qnow.b,3,now); walk0qnow.b=true; if( qnow.b!=0 & !w

19、alkqnow.a0 ) /method=4 means DROP(2) qtotal+=NODE(qnow.a,0,4,now); walkqnow.a0=true; /pour if( qnow.a!=0 & qnow.b!=b ) /method=5 means POUR(1,2) if( qnow.a+qnow.b=b & !walkqnow.a-(b-qnow.b)b ) qtotal+=NODE(qnow.a-(b-qnow.b),b,5,now); walkqnow.a-(b-qnow.b)b=true; else if( qnow.a+qnow.b=a & !walkaqnow.b-(a-qnow.a) ) qtotal+=NODE(a,qnow.b-(a-qnow.a),6,now); walkaqnow.b-(a-qnow.a)=true; else if( qnow.a+qnow.ba & !walkqn

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 教育教学 > 成人教育


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号