【搜索题目】

来源:互联网 发布:unity3d 安卓包调试 编辑:程序博客网 时间:2024/05/16 01:11
/*POJ 1979 模板题目*/#include<cstdio>#include<cstdlib>#include<cstring>int W,H;char dict[22][22];int sum;bool check(int x,int y){    if(!(x>=1&&x<=H&&y>=1&&y<=W))        return false;    return true;}void dfs(int x,int y){    if(!check(x,y))        return ;    if(dict[x][y]=='.'||dict[x][y]=='@'){        sum++;        dict[x][y]='#';        dfs(x,y-1);        dfs(x-1,y);        dfs(x,y+1);        dfs(x+1,y);    }}int main(){    int start_x,start_y;    while(~scanf("%d%d",&W,&H)){        if(W==H && W==0)            break;        for(int i=1;i<=H;i++){            getchar();            for(int j=1;j<=W;j++){                scanf("%c",&dict[i][j]);                if(dict[i][j]=='@'){                    start_x=i;                    start_y=j;                }            }        }        sum=0;        dfs(start_x,start_y);        printf("%d\n",sum);    }}


/*经典DFS()POJ 3009*/#include<cstdio>#include<cstring>int w,h;//记录场地的宽和高int sx,sy,ex,ey;//记录起点和终点坐标int d[4][2] = { {0,-1}, {1,0}, {0,1}, {-1,0} };//存方向变化量int dict[30][30],best;//best记录最优解。dict存地图void dfs(int cx,int cy,int step){//cx,cy记录当前位置。step表示已走多少步    int nx,ny;    if(step>best)//剪枝如果大于目前最优解直接返回        return;    for(int i=0;i<4;i++){        nx=cx+d[i][0];        ny=cy+d[i][1];        if(nx>=h||nx<0||ny<0||ny>=w||dict[nx][ny]==1)//越界或立即有阻挡物剪枝            continue;        while(nx<h&&nx>=0&&ny<w&&ny>=0&&dict[nx][ny]!=1){//一直滑            if(nx==ex&&ny==ey){//若到终点                if(step+1<best)                    best=step+1;                break;            }            nx+=d[i][0];            ny+=d[i][1];        }        if(nx==ex&&ny==ey)//若由于到终点跳出去            continue;        if(nx<h&&nx>=0&&ny<w&&ny>=0){            dict[nx][ny]=0;//若是碰到阻挡物。阻挡物消失。            dfs(nx-d[i][0],ny-d[i][1],step+1);//继续搜索            dict[nx][ny]=1;//还原阻挡物。回溯        }    }}int main(){    while(scanf("%d%d",&w,&h),w||h){        best=12;//初始化best        for(int i=0;i<h;i++)//读取地图        for(int j=0;j<w;j++){            scanf("%d",&dict[i][j]);            if(dict[i][j]==2){                sx=i;                sy=j;            }            if(dict[i][j]==3){                ex=i;                ey=j;            }        }        dfs(sx,sy,0);//深搜        if(best<=10)            printf("%d\n",best);        else            printf("-1\n");    }}
详细代码
http://blog.csdn.net/bossup/article/details/9014701

/*经典BFS()POJ 3669*/#include<cstdio>#include<queue>#include<algorithm>using namespace std;typedef pair<int ,int >P;const int MAX_M=50000;const int MAX_N=400+1;const int INF=0x7fffffff;//输入int M;int X[MAX_M],Y[MAX_M],T[MAX_M];int dict[MAX_N][MAX_N];//保存地图int d[MAX_N][MAX_N];//保存最短步数int z[4][2] = { {0,-1}, {1,0}, {0,1}, {-1,0} };int bfs(){    if(dict[0][0]==0) return -1;  //一开始就被炸    queue<P>que;    que.push(P(0,0));    d[0][0]=0;    while(!que.empty()){        P p=que.front();        que.pop();        //已到达安全位置        int x=p.first,y=p.second;        if(dict[x][y]==INF) return d[x][y];        //4个方向走        for(int i=0;i<4;i++){            int nx=x+z[i][0];            int ny=y+z[i][1];            //判断是否可移动,是否访问过,以及下一个时刻是否安全            if(nx>=0&&ny>=0&&d[nx][ny]==INF&&d[x][y]+1<dict[nx][ny]){                que.push(P(nx,ny));                d[nx][ny]=d[x][y]+1;            }        }    }    return -1;}int solve(){    //初始化地图    for(int i=0;i<MAX_N;i++)        fill(dict[i],dict[i]+MAX_N,INF);     //模拟轰炸场景    for(int i=0;i<M;i++){        dict[X[i]][Y[i]]=min(dict[X[i]][Y[i]],T[i]);        for(int j=0;j<4;j++){            int nx=X[i]+z[j][0];            int ny=Y[i]+z[j][1];            if(nx>=0&&ny>=0)                 dict[nx][ny]=min(dict[nx][ny],T[i]);        }    }    //初始化地图最小步数    for(int i=0;i<MAX_N;i++)        fill(d[i],d[i]+MAX_N,INF);        //宽度优先搜索    int ans=bfs();    printf("%d\n",ans);}int main(){    scanf("%d",&M);    for(int i=0;i<M;i++)        scanf("%d %d %d",&X[i],&Y[i],&T[i]);    solve();}

详细代码

http://www.cnblogs.com/7hat/p/3595630.html

/*POJ  3187题意:已知有N个数分别为1-N,如下图为4个数。相邻两两相加直至只剩下一个数,下图的结果就是16。    3  1   2   4         4   3   6         7   9        16  现在反过来看,告诉你数的个数N和最终结果,问这N个数的初始序列是什么。求出字典序最小的初始序列。上图的初始序列也可以是3 2 1 4,但这不是字典序最小。分析:这题用全排列的方式非常容易做。首先初始化数组为1-N,然后用STL提供的按字典序生成全排列的函数next_permutation即可枚举全排列。对于每一组数,通过计算可以知道它是否能得出已知结果。最先找到的那组数就是字典序最小的值。*/#include<cstdio>#include<algorithm>using namespace std;const int MAX_N=10;int N,finalsum;int a[MAX_N][MAX_N];int calulate(){//计算序列所得的最后和    for(int i=1;i<N;i++){        for(int j=0;j<N-i;j++){            a[i][j]=a[i-1][j]+a[i-1][j+1];        }    }    return a[N-1][0];}void solve(){    for(int i=0;i<N;i++)//初始化序列            a[0][i]=i+1;    do{//按字典序枚举全排列        int sum=calulate();        if(sum==finalsum){            printf("%d",a[0][0]);            for(int i=1;i<N;i++)                printf(" %d",a[0][i]);            printf("\n");            break;        }    }while(next_permutation(a[0],a[0]+N));}int main(){    scanf("%d %d",&N,&finalsum);    solve();    return 0;}

/*题意:给定一个5*5的地图,每个格子上有一个数字。从一个格子出发(上下左右4个方向),走5步将数字连起来可以构造出一个6位数。问该地图可以构造出多少个不同的6位数。分析:可以对每个格子做深度优先遍历,构造出所有数字,但要注意不要重复计数。在这里,我使用了set来保存已构造出的数字,结果就是set中的元素个数。POJ  3050*/#include<cstdio>#include<set>#include<algorithm>using namespace std;int dict[5][5];set<int>st;int d[4][2] = { {0,-1}, {1,0}, {0,1}, {-1,0} };int dfs(int x,int y,int k,int num){    if(k==6){        st.insert(num);        return 0;    }    for(int i=0;i<4;i++){        int nx=x+d[i][0];        int ny=y+d[i][1];        if(nx>=0&&nx<5&&ny>=0&&ny<5){            k++;            dfs(nx,ny,k,num*10+dict[nx][ny]);            k--;//回溯        }    }}void solve(){    for(int i=0;i<5;i++)        for(int j=0;j<5;j++)            dfs(i,j,1,dict[i][j]);    printf("%d\n",st.size());}int main(){    for(int i=0;i<5;i++)        for(int j=0;j<5;j++)            scanf("%d",&dict[i][j]);    solve();}


/*部分和问题NYOJ  927*/#include<cstdio>int a[25];int n,k;bool dfs(int i,int sum){    if(i==n)        return sum==k;    if(dfs(i+1,sum)) return true;    if(dfs(i+1,sum+a[i])) return true;    return false;}int main(){    while(~scanf("%d",&n)){        for(int i=0;i<n;i++)            scanf("%d",&a[i]);        scanf("%d",&k);        if(dfs(0,0))            printf("Of course,I can!\n");        else            printf("Sorry,I can't!\n");    }}



/*深搜或者广搜保存上一节点即可NYOJ 20*/#include<cstdio>#include<vector>#include<cstring>using namespace std;const int MAXN=100010;vector<int>Graph[MAXN];int preNode[MAXN];void DFS(int CurNode){    for(int i=0;i<Graph[CurNode].size();i++){        if(preNode[Graph[CurNode][i]])//如果当前节点已经访问过,那么就继续搜索CurNode的下一个邻接点             continue;        preNode[Graph[CurNode][i]]=CurNode;        DFS(Graph[CurNode][i]);    }}void BFS(int CurNode){    int que[MAXN],qs,qe;    memset(que,0,sizeof(que));    qe=qs=0;    que[qe++]=CurNode;    while(qs<qe){        int u=que[qs++];        for(int i=0;i<Graph[u].size();i++){            if(preNode[Graph[u][i]])                continue;            preNode[Graph[u][i]]=u;            que[qe++]=Graph[u][i];        }    }}int main(){    int test;    int n,start;    int a,b;    scanf("%d",&test);    while(test--){        scanf("%d%d",&n,&start);        memset(Graph,0,sizeof(Graph));        memset(preNode,0,sizeof(preNode));        for(int i=0;i<n-1;i++){            scanf("%d%d",&a,&b);            Graph[a].push_back(b);//只要相邻就添加双向边              Graph[b].push_back(a);        }        preNode[start]=-1;        DFS(start);        for(int i=1;i<=n;i++)            printf("%d ",preNode[i]);    }}

/*连连看HDU  1175*/#include<cstdio>#include<queue>using namespace std;#define INT_MAX 0x3f3f3f3fint direc[4][2]={{0,1},{0,-1},{1,0},{-1,0}};//方向依次为右、左、下、上int dict[1005][1005],vis[1005][1005],m,n;//a为输入的2维向量,visited记录该点是否被访问过了,同时记录有转折次数,如果//新的转折次数小于以前访问时的转折次数那么更新,否则就不更新。typedef struct {    int x,y,dir,corner;//x,y,为行数列数,dir为方向,corner为转角次数。}node;node start,endx;void bfs(){    queue<node>q;    node cur,pre;//用来记录当前的节点和前一个进行比较    start.dir=-1;//开始时无方向    start.corner=0;//开始时转角次数为0    q.push(start);    while(!q.empty()){        pre=q.front();        q.pop();        if(pre.x==endx.x&&pre.y==endx.y){            printf("YES\n");            return ;        }        for(int i=0;i<4;i++){//对节点的四个方向分别进行判断            cur.x=pre.x+direc[i][0];            cur.y=pre.y+direc[i][1];            cur.corner=pre.corner; //令当前转角次数和前一个相同            cur.dir=i;             //当前方向            //前一个不能使开始出,且当前方向和前一个方向不一致是转折次数自增1            if(pre.dir!=cur.dir&&pre.dir!=-1) cur.corner++;                //判断是否出界,转角次数是否超过限制            if(cur.x<1||cur.y<1||cur.x>n||cur.y>m||cur.corner>2) continue;                //如果当前位置有数字存在,且当前位置不是终结位置,违反规则            if(dict[cur.x][cur.y]&&!(cur.x==endx.x&&cur.y==endx.y)) continue;            if(cur.corner<vis[cur.x][cur.y]){                vis[cur.x][cur.y]=cur.corner;                q.push(cur);            }        }    }    printf("NO\n");}int main(){    int q;    while(~scanf("%d%d",&n,&m),n,m){        for(int i=1;i<=n;i++)            for(int j=1;j<=m;j++)                scanf("%d",&dict[i][j]);        scanf("%d",&q);        while(q--){            scanf("%d%d%d%d",&start.x,&start.y,&endx.x,&endx.y);            if(start.x==endx.x&&start.y==endx.y)  {printf("NO\n"); continue;} //开始和结束在同一个位置            //开始和结束位置没有数字或者开始和结束位置的数字不等。            if(!dict[start.x][start.y]||!dict[endx.x][endx.y]||(dict[start.x][start.y]!=dict[endx.x][endx.y]))  {printf("NO\n"); continue;}            for(int i=1;i<=n;i++)                for(int j=1;j<=m;j++)                  vis[i][j]=INT_MAX;            bfs();        }    }}


0 0
原创粉丝点击