[Vjudge][POJ][Tony100K]搜索基础练习

个人整了一些搜索的简单题目,大家可以clone来练习,vjudge链接直接公开了.以下部分代码省略了头文件,总之each就是for循环,rush()就是输入T个样例然后while(T--)

vjudge练习地址:https://vjudge.net/contest/330414

POJ 1426

二进制的数实在太大了,所以用数组下标直接代表二进制数进行搜索可出.

const int maxn = 100+10;
const int INF = 0x3f3f3f3f;


int mod[524286];

void disp(int x)
{
    if(x==0)return ;
    disp(x/2);
    cout<<x%2;
}
int main()
{
    int i;
    int n;
    while(cin>>n)
    {
        if(!n)
            break;
        mod[1]=1%n;
        for(i=2;mod[i-1]!=0;i++)
        {
            //de(i);
            mod[i]=((mod[i/2])*10+i%2)%n;

        }
        i--;
        disp(i);
        cout<<endl;
    }
}

POJ 1321

好久不刷题了,这题出了一堆低级错误
1.dfs的顺序,先判断找到没找到,再判断是不是出口return
2.用字符数组读地图前,必须有一个getchar(),其实用字符串数组更好,一次读一行

#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <bitset>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
#define ll long long
#define mm0(a) memset(a,0,sizeof(a))
#define mm(a,b) memset(a,b,sizeof(a))
#define each(a,b,c) for(int a=b;a<=c;a++)
#define de(x) cout << #x << " " << (x) <<endl
//#define de(x) cout <<""
#define rush() int T;scanf("%d",&T);each(kase,1,T)
#define scan(a,b) scanf("%d%d",&a,&b)
#define fin(a) scanf("%d",&a)
using namespace std;

const int maxn = 1e2+5;
const int INF = 0x3f3f3f3f;
inline int read(){int s=0;char ch=getchar();for(; ch<'0'||ch>'9'; ch=getchar());for(; ch>='0'&&ch<='9'; ch=getchar())s=s*10+ch-'0';return s;}
/**
2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1
*/
char a[10][10];
int m,n;
bool mark[10];
int ans=0;
void dfs(int j,int cnt,int k)//列数 多少个 层数
{
    //de(j);
    //de(cnt);
    //de(k);

    if(cnt==m)
    {
        ans++;
        return;
    }
    if(k>=n)
    {
        return ;
    }//4shunxu
    //puts("fuck");
    //de(n);
    for(int i=0;i<n;i++)
    {
        //de(i);
        //de(j);
        //de(a[i][j]);
        //de(i);
       // de(j);
        if(a[i][j]=='#')
        {
            //空




            //放
            if(mark[i]==0&&cnt<m)
            {
                //de(i);
                //de(j);
                mark[i]=1;
                dfs(j+1,cnt+1,k+1);
                mark[i]=0;
            }
        }
    }
    dfs(j+1,cnt,k+1);
    return;
}
int main()
{

    while(scanf("%d%d",&n,&m)!=EOF&&(m!=-1||n!=-1))
    {
        //de(m);
        //de(n);
        ans=0;
        memset(mark,false,sizeof(mark));//2
        getchar();//4
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                scanf("%c",&a[i][j]);
                //de(a[i][j]);
            }
            getchar();//1
        }
        dfs(0,0,0);
        printf("%d
",ans);//3
    }
    //printf("fuck");

}

POJ 2718

注意不含前导0,但是0是可以有前导0的
初始化,清空数组,最大值赋值,flag放倒都要在while循环开始时(或者BFS开始时)进行处理.增添一个上述变量时,别忘了加上处理.

int a[15];
string str;
int main()
{
    int T;

    scanf("%d",&T);
    getchar();//注意读字符和getline前面一定要有一个getchar
    while(T--)
    {
        int n=0;
        int ans=INF;//错误2,初始化应该在while循环中进行
        getline(cin,str);
        for(int i=0;i<str.length();i++)
        {
            if(str[i]>='0'&&str[i]<='9')
            {
                a[n++]=(int)(str[i]-'0');
            }
        }
        sort(a,a+n);
        do
        {
            if(a[0]==0||(a[n/2]==0&&n>2))continue;//前导0陷阱
            int temp1=0,temp2=0;
            each(i,0,n/2-1)
            {
                temp1*=10;
                temp1+=a[i];
            }
            each(i,n/2,n-1)
            {
                temp2*=10;
                temp2+=a[i];
            }
            //de(temp1);
            //de(temp2);
            ans=min(ans,abs(temp1-temp2));
        }while(next_permutation(a,a+n));
        printf("%d
",ans);
    }
    return 0;
}

POJ 3414

https://www.cnblogs.com/waaaafool/p/11204869.html

#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <bitset>
#include <stack>
#include <vector>
#include <string>
#include <stdio.h>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
#define ll long long
#define mm0(a) memset(a,0,sizeof(a))
#define mm(a,b) memset(a,b,sizeof(a))
#define each(a,b,c) for(int a=b;a<=c;a++)
#define de(x) cout << #x << " " << (x) <<endl
//#define de(x) cout <<""
#define rush() int T;scanf("%d",&T);each(kase,1,T)
#define scan(a,b) scanf("%d%d",&a,&b)
#define fin(a) scanf("%d",&a)
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=1e7+5;
int A,B,C;
int a,b;
int vis[105][105];
struct node
{
    int a,b,step;
    vector<int>op;
    node(int a,int b,int step):a(a),b(b),step(step){}
};
///简洁1
void FILL(int index,int&a,int&b)
{
    if(index==1)a=A;
    if(index==2)b=B;
}
void DROP(int index,int&a,int&b)
{
    if(index==1)a=0;
    if(index==2)b=0;
}
void POUR(int from,int to,int&a,int&b)
{
    if(from==1&&to==2)
    {
        int num=min(a,B-b);
        a-=num;
        b+=num;
        //de(num);
        //de(a);
        //de(b);
    }
    if(from==2&&to==1)
    {
        int num=min(b,A-a);
        a+=num;
        b-=num;
    }
}

node BFS()
{
    memset(vis,0,sizeof(vis));
    queue<node>Q;
    Q.push(node(0,0,0));
    vis[0][0]=1;
    while(!Q.empty())
    {
        node q=Q.front();
        Q.pop();
        if(q.a==C||q.b==C)
            return q;

        //de(q.a);
        //de(q.b);
        //de(q.step);
        each(i,1,6)
        {
            int a=q.a;
            int b=q.b;///这个应该写在里边的
            if(i==1)FILL(1,a,b);
            if(i==2)FILL(2,a,b);
            if(i==3)DROP(1,a,b);
            if(i==4)DROP(2,a,b);
            if(i==5)POUR(1,2,a,b);
            if(i==6)POUR(2,1,a,b);
            //de(i);
            //de(a);
            //de(b);
            if(!vis[a][b])
            {
                vis[a][b]=1;
                node next=node(a,b,q.step+1);
                next.op=q.op;
                next.op.push_back(i);
                ///入队居然没写
                Q.push(next);
            }
        }
    }
    return node(-1,-1,-1);///bfs结束

}
int main()
{
    cin>>A>>B>>C;
    node ans=BFS();///找最先的一个可以这么写

    if(ans.a==-1)printf("impossible
");///这句居然丢了,佛了,先判断不存在,然后在输出step,a==-1居然只写了一个等号
    else cout<<ans.step<<endl;
    for(int i=0;i<ans.op.size();i++)
    {
        if(ans.op[i]==1)puts("FILL(1)");
        if(ans.op[i]==2)puts("FILL(2)");
        if(ans.op[i]==3)puts("DROP(1)");
        if(ans.op[i]==4)puts("DROP(2)");
        if(ans.op[i]==5)puts("POUR(1,2)");
        if(ans.op[i]==6)puts("POUR(2,1)");


    }

    return 0;
}


爷写的一直超时,佛了.

#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <bitset>
#include <stack>
#include <vector>
#include <string>
#include <stdio.h>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
#define ll long long
#define mm0(a) memset(a,0,sizeof(a))
#define mm(a,b) memset(a,b,sizeof(a))
#define each(a,b,c) for(int a=b;a<=c;a++)
#define de(x) cout << #x << " " << (x) <<endl
//#define de(x) cout <<""
#define rush() int T;scanf("%d",&T);each(kase,1,T)
#define scan(a,b) scanf("%d%d",&a,&b)
#define fin(a) scanf("%d",&a)
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=1e7+5;


int vis[105][105];
string ans[maxn];
int father[maxn];
int cur=0;///从1开始
struct node{
    node*father;
    string op;
    int a,b;
    int id;
    int cnt;
    node(int a,int b,string op="",int id=0,int cnt=0):a(a),b(b),op(op),id(id),cnt(cnt){}
};
int A,B,c;
void print(int x)
{
    if(x==1)return ;
    print(father[x]);
    cout<<ans[x]<<endl;
}
void bfs()
{
    queue<node>Q;
    while(!Q.empty())Q.pop();
    Q.push(node(0,0,"",++cur,0));
    ans[1]="";
    ///这里把头结点压进去时居然没有vis
    vis[0][0]=1;
    while(!Q.empty())
    {
        node q=Q.front();
        //de(q.a);
        //de(q.b);
        //de(q.op);
        int cnt=q.cnt;
        int id=q.id;
        Q.pop();
        if(q.a==c||q.b==c)
        {
            //输出
            cout<<cnt<<endl;
            print(id);

            return ;
        }
        else
        {
            //FILL(1)
            if(!vis[A][q.b])
            {
                vis[A][q.b]=1;
                Q.push(node(A,q.b,"FILL(1)",++cur,cnt+1));
                ans[cur]="FILL(1)";
                father[cur]=id;
            }
            //FILL(2)
            if(!vis[q.a][B])
            {
                vis[q.a][B]=1;
                Q.push(node(q.a,B,"FILL(2)",++cur,cnt+1));
                ans[cur]="FILL(2)";
                father[cur]=id;
            }
            //DROP(1)
            if(!vis[0][q.b])
            {
                vis[0][q.b]=1;
                Q.push(node(0,q.b,"DROP(1)",++cur,cnt+1));
                ans[cur]="DROP(1)";
                father[cur]=id;
            }
            if(!vis[q.a][0])
            {
                vis[q.a][0]=1;
                Q.push(node(q.a,0,"DROP(2)",++cur,cnt+1));
                ans[cur]="DROP(2)";
                father[cur]=id;
            }
            //POUR(1,2)
            int num=min(q.a,B-q.b);
            int na=q.a-num;
            int nb=q.b+num;
            if(!vis[na][nb])
            {
                vis[na][nb]=1;
                Q.push(node(na,nb,"POUR(1,2)",++cur,cnt+1));
                ans[cur]="POUR(1,2)";
                father[cur]=id;
            }
            //POUR(2,1)
            num=min(q.b,A-q.a);
            na=q.a+num;
            nb=q.b-num;
            if(!vis[na][nb])
            {
                vis[na][nb]=1;
                Q.push(node(na,nb,"POUR(2,1)",++cur,cnt+1));
                ans[cur]="POUR(2,1)";
                father[cur]=id;
            }
        }
    }
    cout<<"impossible"<<endl;

}
int main()
{
    memset(vis,0,sizeof(vis));
    cin>>A>>B>>c;
    bfs();
}

POJ 1416

现在你要研发一种新型的碎纸机,待粉碎的纸上面有一串数字,要求把纸粉碎成的几片上的数字的和尽量接近而不能超过给定的数字target number。比如:一片纸上的数字为12346,target number为50,那么就可以把纸粉碎为1、2、34、6,其加和为43,是所有粉碎方法中最接近50而不超过50的最优解。

相等和error可以在一开始就判断出来,不用中间整个flag去判断了DFS的逻辑非常简单,但是中间过程不好保存,一开始用的栈,但在回溯过程中都pop完了,所以用数组模拟栈,在大于ans时,设置ansS和anscur,表示答案的栈和栈的长度,然后记录一下,输出ansS即可.

1.每回合flag也要清0
2.这种切段的搜索,最后不需要再切一刀,自然就返回了.

int c;
int n;
char num[10];
int seg[10][10];
int len;
///////////
int S[maxn];
int cur=0;
/////////////
void init()
{
    len=strlen(num);
    for(int i=0;i<len;i++)
    {
        for(int j=i;j<len;j++)
        {
            int temp=0;
            each(k,i,j)
            {
                //de(i);
                //de(j);
                temp*=10;
                temp+=(num[k]-'0');
            }
            seg[i][j]=temp;
        }
    }
}
int rej_flag=0;
int ans=0;
int ansS[10];
int anscur;
void dfs(int i,int sum)
{
   // de(i);
   // de(sum);
    ///出口
    if(i>=len)
    {
        if(sum<=c)
        {
            if(sum>ans)
            {
                ans=sum;
                //ansqie=qie;
                rej_flag=0;
                /*
                each(ii,0,cur-1)
                   {
                       printf("%d ",S[ii]);
                   }
                   puts("");*/
                each(ii,0,cur-1)
                {
                    ansS[ii]=S[ii];

                }
                anscur=cur;///cur!!!!!1

            }
            else if(sum==ans)
            {
                rej_flag=1;
            }
        }
        return;
    }
    int temp=0;
    for(int j=i;j<len;j++)
    {
        temp*=10;
        temp+=seg[j][j];
        ///qie
        S[cur++]=temp;
        dfs(j+1,sum+temp);
        cur--;
        ///buqie
    }
    ///dfs(len,sum+temp);///相当于返回了,这刀是不需要切的
}
int main()
{
   while(true)
   {
       ans=0;///qingkong
       rej_flag=0;
        cur=0;
       scanf("%d %s",&c,num);
       //de(c);
       //de(num);
       sscanf(num,"%d",&n);
       if(n==0&&c==0)break;
       if(n==c)
       {
           printf("%d %d
",n,c);
           continue;
       }
       ///这里给强行来一个
       int summ=0;
       for(int i=0;i<strlen(num);i++)
       {
           summ+=num[i]-'0';
       }
       if(summ>c)
       {
           printf("error
");
           continue;
       }
       init();
       dfs(0,0);
       if(rej_flag)
       {
           puts("rejected");
       }
       else
       {
           printf("%d ",ans);
           each(ii,0,anscur-1)
           {
               printf("%d",ansS[ii]);
               if(ii!=anscur-1)printf(" ");
               else printf("
");
           }
       }


   }

    return 0;
}

POJ 2362

判断到了出口一定要return,这都丢了,真是憨憨

#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <bitset>
#include <stack>
#include <vector>
#include <string>
#include <stdio.h>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
#define ll long long
#define mm0(a) memset(a,0,sizeof(a))
#define mm(a,b) memset(a,b,sizeof(a))
#define each(a,b,c) for(int a=b;a<=c;a++)
#define de(x) cout << #x << " " << (x) <<endl
//#define de(x) cout <<""
#define rush() int T;scanf("%d",&T);each(kase,1,T)
#define scan(a,b) scanf("%d%d",&a,&b)
#define fin(a) scanf("%d",&a)
using namespace std;
const int INF=0x3f3f3f3f;
/*
3
4 1 1 1 1
5 10 20 30 40 50
8 1 7 2 6 4 4 3 5

7 6 5 4 4 3 2 1
*/
int vis[25];
int a[25];
int m;
int cmp(int a,int b)
{
    return a>b;
}
int flag;
int side;
/// dfs写的有些别扭,参考人家的for循环bool写法吧
bool dfs(int k,int len,int s)///s为开始搜索的点
{
    //de(k);
   // de(len);
   // de(s);
    if(k==3)return true;
    for(int i=s;i<=m;i++)
    {
        if(vis[i])
            continue;
        vis[i]=true;
       // de(a[i]);
        //de(side);
       // de(len);
        if(len+a[i]<side)
        {
            if(dfs(k,len+a[i],i+1))///i+1?? 写大括号啊!!!草return
            return true;
        }

        else if(len+a[i]==side)
        {
            //de(len+a[i]);
            if(dfs(k+1,0,1))
                return true;
        }
        vis[i]=false;
    }
    return false;
}
/*
void dfs(int i,int k,int num)//1 0 0
{
    //de(i);
    //de(k);
    //de(num);
    if(i>m)return;///划定边界
    if(k==3)flag=true;
    if(!vis[i])
    {
        vis[i]=true;
        num+=a[i];
        if(num>side)
        {
            vis[i]=false;
        }
        else if(num==side)
        {
            dfs(1,k+1,0);
        }
        else
        {
            dfs(i+1,k,num);///这个位置选了
            vis[i]=false;///回溯
            dfs(i+1,k,num-a[i]);///这个位置没选
        }
    }
    else///如果访问过了
    {
        dfs(i+1,k,num);
    }
}*/
int main()
{
    rush()
    {
        flag=false;

        memset(vis,0,sizeof(vis));
        scanf("%d",&m);
        int sum=0;
        each(i,1,m)
            scanf("%d",&a[i]),sum+=a[i];
        if(m<4||sum%4!=0)
        {
            printf("no
");
            continue;
        }

        side=sum/4;
        sort(a+1,a+1+m,cmp);
       
        if(dfs(0,0,1))
            printf("yes
");
        else printf("no
");///de没有删干净
        
    }
}

POJ 3126

就是从一个四位数到另一个四位数,每次只能变化一位,而且中间的过程必须也是质数,问最少变化多少位。

1.判断质数用了优化,for循环判断了不能等于自身,搜索题只要有任何优化剪枝的方法都要用上!除非没有罚失。
2.必须保持四位数,即千位不能为0,只要有这种数位题一定有这种前导0陷阱。
3.if没有vis,那么立即打上vis标记,vis标记是在入队的时候打的,在for循环前出队的节点如果是答案,就return
4.用数组模拟队列更快一点!!!下次一定学。

用剪枝快速判断素数

bool JudgePrime(int digit)
{
	if(digit==2 || digit==3)
		return true;
	else if(digit<=1 || digit%2==0)
		return false;
	else if(digit>3)
	{
		for(int i=3;i*i<=digit;i+=2)///注意步长是2
			if(digit%i==0)
				return false;
		return true;
	}
}

#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <bitset>
#include <stack>
#include <vector>
#include <string>
#include <stdio.h>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
#define ll long long
#define mm0(a) memset(a,0,sizeof(a))
#define mm(a,b) memset(a,b,sizeof(a))
#define each(a,b,c) for(int a=b;a<=c;a++)
#define de(x) cout << #x << " " << (x) <<endl
//#define de(x) cout <<""
#define rush() int T;scanf("%d",&T);each(kase,1,T)
#define scan(a,b) scanf("%d%d",&a,&b)
#define fin(a) scanf("%d",&a)
using namespace std;
const int INF=0x3f3f3f3f;
int a,b;
bool vis[15000];
int ans;
bool judge(int x)
{
    if(x==2||x==3)return true;
    else if(x<=1||x%2==0)
        return false;
    else if(x>3)
    {
        for(int i=3;i*i<=x;i+=2)
        {
            if(x%i==0)return false;

        }
        return true;
    }
}
struct node
{
    int v;
    int step;
    node(int v,int step):v(v),step(step){}
};
void bfs()
{
    //先放队首
    ///用数组模拟队列更快一点!!!
    queue<node>Q;
    while(!Q.empty())Q.pop();
    Q.push(node(a,0));
    vis[a]=true;
    while(!Q.empty())
    {
        node q=Q.front();
        Q.pop();
        int v=q.v;
        //de(v);

        int step=q.step;
        //de(step);
        int ge=v%10;
        int shi=(v%100)/10;
        int bai=(v%1000)/100;
        int qian=v/1000;
        if(v==b)
        {
            ans=step;
            return;
        }
        ///ge
        for(int i=0;i<=9;i++)
        {
            int nv=qian*1000+bai*100+shi*10+i;
            if(!vis[nv]&&nv!=v&&judge(nv))///只要有优化的方法就要用上
            {
                vis[nv]=true;///如果没有vis,那么立即打上vis标记
                Q.push(node(nv,step+1));
            }
        }
        ///shi
        for(int i=0;i<=9;i++)
        {
            int nv=qian*1000+bai*100+i*10+ge;
            if(!vis[nv]&&nv!=v&&judge(nv))///只要有优化的方法就要用上
            {
                vis[nv]=true;///如果没有vis,那么立即打上vis标记
                Q.push(node(nv,step+1));
            }
        }
        ///bai
        for(int i=0;i<=9;i++)
        {
            int nv=qian*1000+i*100+shi*10+ge;
            if(!vis[nv]&&nv!=v&&judge(nv))///只要有优化的方法就要用上
            {
                vis[nv]=true;///如果没有vis,那么立即打上vis标记
                Q.push(node(nv,step+1));
            }
        }
        ///qian///注意最高位不能为0,前导0陷阱
        for(int i=1;i<=9;i++)
        {
            int nv=i*1000+bai*100+shi*10+ge;
            if(!vis[nv]&&nv!=v&&judge(nv))///只要有优化的方法就要用上
            {
                vis[nv]=true;///如果没有vis,那么立即打上vis标记
                Q.push(node(nv,step+1));
            }
        }

    }

}
/*
3
1033 8179
1373 8017
1033 1033
*/
int main()
{
    rush()
    {
        cin>>a>>b;
        mm0(vis);
        ans=INF;
        bfs();
        cout<<ans<<endl;
    }
    return 0;
}

POJ 3009

先说一下题意:(1) 一个球有四个方向可以走,上下左右;题目中提到这个球的运动方向受到了限制,只能走直线,沿着一个方向一直走下去,并且在这个方向上停止的条件是当前位置的下一个位置是障碍物,那么球会在当前位置停下,并且当前位置的下一位置的障碍物消失,那么这种情况算滚动1次;
(2)如果滚动次数超过10次,那么就输出-1,正因为这样,可以暴力穷举;

                          (3)   另外一种情况:如果球滚出界了,那么游戏结束;

思路: 这道题一看感觉无从下手,和其他题不一样,搜索不是一步一步的,而是整条直线的搜(其实是把直线分解成若干步);

就是一个简单的直线搜索,每次算一步就行了,结果还是写出来好多错误,甚至没有自信,这种搜索还是当年眼高手低所以现在十分垃圾。

1.judge 函数居然没有return false;实在不行return个表达式也可以啊。
2.n,m写反了,干脆就写hang和lie得了。
3.step不用增加,每次就+1个就行了,还是之前的惯性。
4.注意每回合清空数组,并把ans赋成最大值。

#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <bitset>
#include <stack>
#include <vector>
#include <string>
#include <stdio.h>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
#define ll long long
#define mm0(a) memset(a,0,sizeof(a))
#define mm(a,b) memset(a,b,sizeof(a))
#define each(a,b,c) for(int a=b;a<=c;a++)
#define de(x) cout << #x << " " << (x) <<endl
//#define de(x) cout <<""
#define rush() int T;scanf("%d",&T);each(kase,1,T)
#define scan(a,b) scanf("%d%d",&a,&b)
#define fin(a) scanf("%d",&a)
using namespace std;
int a[25][25];
int m,n;
int sx,sy,ex,ey;
int ans=0x3f3f3f3f;
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
bool judge(int x,int y)
{
    if(x>=1&&x<=m&&y>=1&&y<=n&&a[x][y]!=1)return true;
    else return false;///return false miss!!
}
void dfs(int x,int y,int step)
{
    //de(x);
    //de(y);
    //de(step);
    if(step>10)return;

    each(i,0,3)
    {
        int nx=x+dx[i];
        int ny=y+dy[i];
        int ok=0;
        ///step不用增加做错了!!!!
       
        while(judge(nx,ny))
        {
            //de(nx);
            //de(ny);
            ok=1;///ok??????
            if(a[nx][ny]==3)
            {
                ans=min(ans,step);
            }
            //de(ans);
            nx=nx+dx[i];
            ny=ny+dy[i];

        }
        //如果是撞墙了,越界就不管了
        if(a[nx][ny]==1&&ok)///?????????????????????????????????????
        {
            a[nx][ny]=0;
            dfs(nx-dx[i],ny-dy[i],step+1);///方向又搜错了
            a[nx][ny]=1;

        }
    }
}
/***
2 1
3 2
6 6
1 0 0 2 1 0
1 1 0 0 0 0
0 0 0 0 0 3
0 0 0 0 0 0
1 0 0 0 0 1
0 1 1 1 1 1
6 1
1 1 2 1 1 3
6 1
1 0 2 1 1 3
12 1
2 0 1 1 1 1 1 1 1 1 1 3
13 1
2 0 1 1 1 1 1 1 1 1 1 1 3
0 0
*/

int main()
{
    while(scanf("%d%d",&n,&m)&&!(m==0&&n==0))
    {
        ans=0x3f3f3f3f;///注意每回合清空
        memset(a,0,sizeof(a));
        each(i,1,m)
        {
            each(j,1,n)///m,n写反了
            {
                scanf("%d",&a[i][j]);
                if(a[i][j]==2)
                {
                    sx=i;
                    sy=j;
                }
                if(a[i][j]==3)
                {
                    ex=i;
                    ey=j;
                }
            }
        }
        dfs(sx,sy,1);
        if(ans<=10)
            cout<<ans<<endl;
        else cout<<-1<<endl;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Tony100K/p/11608962.html