【搜索题目】

/*
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 0x3f3f3f3f
int 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();
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值