随笔分类 -  搜索题

摘要:原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4016题意:从给出的N个数中,选出K个数进行与运算,求出最小值一看到这题目,哎,就知道暴力是绝对超时的,可是之后,就没之后……………………看了网上的思路,这剪枝太有技巧了,orz思路如下:1.从当前值开始,如果选上剩下的所有,也不能小于已得最优值的话,返回。2.最优值不用等到累积选到k数才更新,而是不断更新,因为与运算结果比原来两个都小,所以这也是一个剪枝。3.预处理,从小到大排序,可想而知,先选小的,得到的最优值更接近于结果,是个强剪枝,没有这个2900ms+,加上600ms+。太强大了原文的链接 阅读全文
posted @ 2011-09-14 22:59 枕边梦 阅读(510) 评论(0) 推荐(0)
摘要:比较简单的搜索,不过我的内存开得太大了,不知道怎么缩减一开始内存开得太小了,忘了可能有一步是X*2,所以总数值可能大于100000,所以RE了#include<iostream>#include<string>#include<queue>using namespace std;int n,k;int vis[200002];struct node{ int x,cnt; node(int _x=0,int _cnt=0):x(_x),cnt(_cnt){};}; queue<node> Q;void bfs(){ memset(vis,0,si 阅读全文
posted @ 2011-08-12 00:47 枕边梦 阅读(227) 评论(0) 推荐(0)
摘要:天啊,漏了一个条件,搞了半天,默认从第0个problem 开始做起,唉,我枚举所有的问题了……………………在DFS过程中,只要把最大深度记录下来即可,不需要其他#include<iostream>#include<string>using namespace std;int n,map[15][15],ans;bool vis[15];void dfs(int i,int j,int deep){ if(deep>ans)ans=deep; for(int k=1;k<=n;k++) { if(vis[k]||k==j) continue; if(map[i 阅读全文
posted @ 2011-08-11 23:58 枕边梦 阅读(257) 评论(0) 推荐(0)
摘要:这题目,唉,一开始以为很简单的,就是枚举每一个KFC到M和Y的距离,求出最短的,结果TLE了之后,突然想到了双向搜索,天呐,又郁闷了很久,从来都没写过,一时不只从何下手,而且,不知道搜索时的停止条件该如果设置,结果就……回到一开始最不想做的,就是分别用调用俩次BFS,算出M和Y到每一个KFC的最短距离,再累加求最短即可这时候要注意,BFS退出的条件是遍历完所有的点,所以遇到‘@’时,把相应时间累加之后,还是要继续搜另外,有一点也是十分重要的 ,就是未必每一个KFC都是可达的,所以要多加一步判断………唉………#include<iostream>#include<string&g 阅读全文
posted @ 2011-08-11 22:53 枕边梦 阅读(354) 评论(0) 推荐(0)
摘要:做了这么久的搜索,终于还是碰到了N皇后问题,之前一直都不敢去触碰,今天还是无奈的做了我的代码比较乱,也比较慢,看下大牛的代码吧,感觉好精炼呀,而且效率很高的说map[],下标表示所在行,值表示所在列哈,判断是否在同一对角线上居然是这么判断的,好神奇要事先打表View Code #include<iostream> #include<string>using namespace std;int n,map[20],des[20],cnt,a[11]; void DFS( int num ) { if( num == n + 1 ) { ++cnt... 阅读全文
posted @ 2011-08-11 20:46 枕边梦 阅读(210) 评论(0) 推荐(0)
摘要:给了一个8*8的地图,时间要求却是5000ms ,似乎就是要遍历整个地图,枚举设置的封锁区域一开始是想把所有可行的路径找出来,再看一下重复路径,判断应该设置多少个封锁区域,但是一旦设置了一个封锁区域,就又出现了不同的路径出来,这样,就跟枚举有何差别呢?思路(大牛的):封锁出口或者入口周围的格子.最多需要4个封锁点.所以我们可以采取这样的策略:1.寻找一条盗贼的可行路线,如果没有,返回0.2.计算封锁出口和入口四周需要的封锁点数量,取小的一个,假设是k,k <=43.从少到多,遍历所有封锁点个数小于k的方案,验证是否是一条有效的覆盖方案(可以通过是否阻止了1中的盗贼线路进行快速验证).如果 阅读全文
posted @ 2011-08-11 17:04 枕边梦 阅读(468) 评论(0) 推荐(0)
摘要:这题目跟之前的连连看还有hdu1072 都很像,就是路径受转弯次数的限制,这时vis[][]数组并非用来记录一个点是否已被访问过,而是记录经过该点的最少转弯次数,若经过该点存在更少的转弯次数的路径,则该点可以再次入队看代码吧#include<iostream>#include<queue>using namespace std;char map[101][101];int n,m,T,ei,ej,dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};int vis[101][101];struct node{ int x,y,di,turn;};n 阅读全文
posted @ 2011-08-11 09:43 枕边梦 阅读(193) 评论(0) 推荐(0)
摘要:终于还是AC了,可是WA了N多次了呀,唉,忽略了一个要点,就是在广搜的时候,一个点可以不止被通过一次,好郁闷呀,确实如此,看了大牛给的测试例子,通过了这个例子,接着就AC了得再开一个数组记录到达该点的方向主体是用BFS枚举所有可推点的状态,用DFS判断推箱工能否到达箱子的后面看下这个测试例子5 30 0 00 0 00 2 01 4 11 3 1答案是 4#include<iostream>#include<queue>using namespace std;int map[8][8],n,m,ei,ej,a,b,dir[4][2]={{1,0},{-1,0},{0,1 阅读全文
posted @ 2011-08-10 18:44 枕边梦 阅读(192) 评论(0) 推荐(0)
摘要:额,简单的DFS#include<iostream>#include<queue>using namespace std;int map[26][26];bool vis[26][26];struct node{ int x; node(int _x=0):x(_x){};};bool bfs(){ queue<node> Q; Q.push(node(1)); while(!Q.empty()) { node t=Q.front(); Q.pop(); for(int i=0;i<26;i++) { if(map[t.x][i]&&i 阅读全文
posted @ 2011-08-10 13:51 枕边梦 阅读(217) 评论(0) 推荐(0)
摘要:一个早上了,整整一个早上了,我的天啊,错误是大把大把的可是思路明明很简单,这题是用BFS做的,可是不能紧紧标记一个点是否已经访问过,这样直接WA,因为访问过的不符合条件的点,很可能是因为转了太多的弯,但完全有可能存在转的弯比较少的路径在之后访问该点,所以vis[][]数组是用来保存访问过该点的最少的转弯次数,这样,只要访问该点,该点的转弯次数小于之前访问该店的最小转弯次数,则可以入队我很不明白,我之前有些为什么还会MLE……#include <iostream>#define MAXN 1001#include <queue>using namespace std;in 阅读全文
posted @ 2011-08-10 12:48 枕边梦 阅读(258) 评论(1) 推荐(0)
摘要:一个早上已经过了呀,迷宫问题已经做了好几道了呀,这题居然还要搞半天呀,一开始觉得用DFS直接一点,很好写,可是很果断的超时了,所以还是BFS了之后,题目要求不能回头,但是可能转多个弯之后又回到走过的点,但还是有可能过去的,因为可能是从不同方向移动到这个点,所以,所以用一个三维的数组记录每一个点的状态,每个点有五种状态,没走过,还有从四个方向中的一个方向移动到该点,vis[81][81][5](一开始开小了,直接挂了一次),注意到这一点之后,我想应该就不难A 了,但是敲代码过程中的细节问题还是很多的,具体看代码吧#include<iostream>#include<queue& 阅读全文
posted @ 2011-08-08 13:53 枕边梦 阅读(568) 评论(0) 推荐(0)
摘要:刚开始看到这题都吓到了,第一感觉就是不能记录已走过的点,一旦记录了,那假设钥匙在对面,门在这边,那拿完钥匙就回不来了;可是,如果不记录的话,那岂不是在整个地图了乱窜,绝对超时,甚至是死循环;之后,想了想,把每个点在入队列的时候,记录下状态每一个点的状态,即又有没有拿到钥匙,拿到哪几种钥匙之类的,如果回溯时,俩点的状态一样,则没必要入队,这确实是一种可行的办法,可是想到这里,突然,想到,要对每一个点保存16种状态,那内存肯定要爆了呀,结果思路就这么停了,想不出别的办法了……查了一下,原来记录状态是用位运算保存呀,郁闷呐,亏我知道这东西存在,亏我还用过位运算保存过一个数字是否出现过,结果我居然一点 阅读全文
posted @ 2011-08-05 11:37 枕边梦 阅读(1103) 评论(0) 推荐(0)
摘要:额,还是BFS,只不过分层进行而已,注意时空机部分的就好了真的好熟了呀,可是每次总有一些小错误要改好久郁闷呐#include<iostream>#include<queue>using namespace std;char map[2][10][10];int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}},n,m,T;bool vis[2][10][10],flag;struct node { int x,y,z,cnt; node(int _z=0,int _x=0,int _y=0,int _cnt=0):z(_z),x(_x),y(_ 阅读全文
posted @ 2011-08-04 00:49 枕边梦 阅读(212) 评论(0) 推荐(0)
摘要:额,自己的代码比较水,用普通的方法做的,内存开得太大了View Code #include"stdio.h"#define maxn 11000000__int64 q[maxn];int n;void bfs(){ int i,j; __int64 x; q[0]=1; i=0;j=1; while(i<j) { x=q[i]; if(x%n==0) { printf("%I64d\n",x); break; } x*=10; q[j++]=x; q[j++]=x+1; i++; }}int main(){ while(scanf("% 阅读全文
posted @ 2011-08-03 21:03 枕边梦 阅读(195) 评论(0) 推荐(0)
摘要:这题还真是诡异,明明思路很清晰,BFS也很熟练 的敲出来了,可就是改了半天,原来问题在这里,“Harry从来不在楼梯上停留”,这里提示的很明显了,他除了不再楼梯上停留,其他地方是可以停留的,当然,也就只有在遇到楼梯,又暂时过不去时,才有必要在原地停留,郁闷呀,疏忽了这里,wa了好几次……hdu1180 代码#include <iostream>#include <queue>using namespace std;struct Node{ int x, y, time; Node(int _x=0,int _y=0,int _time=0):x(_x),y(_y),ti 阅读全文
posted @ 2011-08-03 11:57 枕边梦 阅读(319) 评论(0) 推荐(0)
摘要:优先队列+BFS+保存路径额,先记录前驱,再用栈输出路径,其他的,都快成模板了,最近打得很熟,就是输出的时候,一些小错误改了半天ORZ#include<iostream>#include<queue>#include<algorithm>#include<stack>using namespace std;char map[101][101];int vis[101][101],n,m,mins;bool rescue;int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};struct node{ int x,y,c 阅读全文
posted @ 2011-08-02 22:06 枕边梦 阅读(509) 评论(0) 推荐(0)
摘要:hdu2141唉,是我 想多了,用普通方法拼命剪枝,还是TLE直接将前俩个数组的和求出来并保存,之后就是一个二分查找的过程了二分的俩种写法第一种#include<iostream>#include<algorithm>#include<string>using namespace std;int a[501],b[501],c[501],f[250001];bool bin_search(int n,int key){ int left=0,right=n-1,mid=0,temp; while(left<right) { temp=mid; mi.. 阅读全文
posted @ 2011-08-02 17:10 枕边梦 阅读(534) 评论(0) 推荐(0)
摘要:用栈来模拟操作,主要还是DFS注意回溯条件,还有遍历失败后的操作就没什么了#include<iostream>#include<stack>#include<string>#include<algorithm>using namespace std;char b[200],b1[100],b2[100];//b[]保存路径stack<char> ST;int len1,len2;int cmp( const void* c1,const void* c2){ return *(char *)c1-*(char *)c2;}void d 阅读全文
posted @ 2011-08-02 14:15 枕边梦 阅读(181) 评论(0) 推荐(0)
摘要:嘿嘿,终于还是AC了,DFS多开了几个数组,稍微加快了一点点,不然就超时了,原来,一点一点的剪枝,还是有那么一点点用滴,看代码吧#include<iostream>#include<queue>using namespace std;int prime[]={2,3,5,7,11,13,17,19,23,29,31,37};//相邻俩个数的和顶多就37,所以把其中的所有素数都直接打表了int a[20],b[20],n;bool hash1[40];void init()//哈希表{ memset(hash1,0,sizeof(hash1)); for(int i=0; 阅读全文
posted @ 2011-08-02 00:30 枕边梦 阅读(143) 评论(0) 推荐(0)
摘要:嘿嘿,题目罗嗦了半天,其实意思很简单,就是给定一个目标值target,再给你一个备选字符串(5~12个字符),要你在这个字符串里选5个出来,满足题中给定的等式,并且你选择的这5个字符组成的字符串必须是所有可能情况中按字典序最大的情况。 简单分析下就可以看出,就是一个组合问题,问题解的最大规模就是12取5,就是12*11*10*9*8*7,而最小规模是5取5,所以应该用枚举法就可以搞定。不过,枚举之前先排个序,就可以保证输出的是符合要求的最大的那个了#include<iostream>#include<string>using namespace std;int cmp( 阅读全文
posted @ 2011-08-01 22:13 枕边梦 阅读(1875) 评论(0) 推荐(0)