• 挑战程序设计竞赛 2.1 最基础的“穷竭搜索”


    【Summarize】

      1.划分为两堆的无序模型可以利用二进制枚举,

      而划分为两堆的有序模型可以枚举全排列取定长

      2.当搜索终态唯一时可考虑逆向搜索

    POJ 1979:Red and Black

    /*
        一个矩形的屋子里有一个人,他可以踩黑格子,但是不能踩红格子,
        他现在站在一个黑格子上,告诉你房间的布局,
        这个人可以向上下左右四个方向移动,问这个人最多能到达的格子数
    */
    #include <cstdio>
    #include <cstring>
    using namespace std;
    int W,H,ans,vis[35][35];
    char mp[35][35];
    const int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
    bool check(int x,int y){
        if(vis[x][y])return 0;
        if(mp[x][y]=='.'&&x&&y&&x<=H&&y<=W)return 1;
        return 0;
    }
    void dfs(int x,int y){
        vis[x][y]=1;ans++;
        for(int i=0;i<4;i++){
            if(check(x+dx[i],y+dy[i]))dfs(x+dx[i],y+dy[i]);
        }return;
    }
    int main(){
        while(~scanf("%d%d",&W,&H),W+H){
            ans=0; memset(vis,0,sizeof(vis));
            for(int i=1;i<=H;i++)scanf("%s",mp[i]+1);
            for(int i=1;i<=H;i++)for(int j=1;j<=W;j++)
            if(mp[i][j]=='@')dfs(i,j);
            printf("%d
    ",ans);
        }return 0;
    }

    AOJ 0118:Property Distribution

    /*
        颜色相同且相邻的块属于同一个果园,求果园的总个数
    */
    #include <cstdio>
    #include <cstring>
    using namespace std;
    int W,H,ans,vis[105][105];
    char mp[105][105];
    const int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
    bool check(int x,int y,char c){
        if(vis[x][y])return 0;
        if(mp[x][y]==c&&x&&y&&x<=H&&y<=W)return 1;
        return 0;
    }
    void dfs(int x,int y,char c){
        vis[x][y]=1;
        for(int i=0;i<4;i++){
            if(check(x+dx[i],y+dy[i],c))dfs(x+dx[i],y+dy[i],c);
        }return;
    }
    int main(){
        while(~scanf("%d%d",&H,&W),W+H){
            ans=0; memset(vis,0,sizeof(vis));
            for(int i=1;i<=H;i++)scanf("%s",mp[i]+1);
            for(int i=1;i<=H;i++)for(int j=1;j<=W;j++)
            if(!vis[i][j]){ans++;dfs(i,j,mp[i][j]);}
            printf("%d
    ",ans);
        }return 0;
    }

    AOJ 0033:Ball

    /*
        给出十个小球排成一列,从两个出口出去,问能否做到将十个球按一定分配,
        使得两个出口出来的球标号都是递增
    */
    #include <cstdio>
    int T,a[10];
    void solve(){
        for(int i=0;i<(1<<10);i++){
            int pre1=0,pre2=0,flag=1;
            for(int j=0;j<10;j++){
                if((1<<j)&i){
                    if(a[j]<pre1){flag=0;break;}
                    pre1=a[j];
                }else{
                    if(a[j]<pre2){flag=0;break;}
                    pre2=a[j];
                }
            }if(flag){puts("YES");return;}
        }puts("NO"); return;
    }
    int main(){
        scanf("%d",&T);
        while(T--){
            for(int i=0;i<10;i++)scanf("%d",a+i);
            solve();
        }return 0;
    }

    POJ 3009:Curling 2.0

    /*
        将一块石头从起点滚到终点,一次必须要滚到碰到石头才会停下来,
        而碰到的石头会破碎,如果十步内能到终点则输出步数,否则输出无解
    */
    #include <cstdio>
    #include  <algorithm>
    using namespace std;
    int mp[25][25],ans=0,W,H;
    const int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
    bool check(int x,int y){
        if(mp[x][y]%2==0&&x&&y&&x<=H&&y<=W)return 1;
        return 0;
    }
    bool in(int x,int y){
        if(x&&y&&x<=H&&y<=W)return 1;
        return 0;
    }
    void dfs(int x,int y,int d){
        if(d>=10)return;
        for(int i=0;i<4;i++){
            int nx=x,ny=y,flag=0;
            while(check(nx+dx[i],ny+dy[i])){
                nx+=dx[i],ny+=dy[i];flag=1;
            }if(in(nx+dx[i],ny+dy[i])){
                if(mp[nx+dx[i]][ny+dy[i]]==3){ans=min(ans,d+1);return;}
                if(flag){
                    mp[nx+dx[i]][ny+dy[i]]=0;
                    dfs(nx,ny,d+1);
                    mp[nx+dx[i]][ny+dy[i]]=1;
                }
            }
        }
    }
    int main(){
        while(~scanf("%d%d",&W,&H),W+H){
            ans=11;
            for(int i=1;i<=H;i++){
                for(int j=1;j<=W;j++){
                    scanf("%d",&mp[i][j]);
                }
            }
            for(int i=1;i<=H;i++){
                for(int j=1;j<=W;j++){
                    if(mp[i][j]==2)dfs(i,j,0);
                }
            }if(ans>10)puts("-1");
            else printf("%d
    ",ans);
        }return 0;
    }

    AOJ 0558:Cheese

    /*
        求从起点开始依次到1,2,……,N,的总距离的最小值
    */
    #include <cstdio>
    #include <queue> 
    #include <cstring>
    using namespace std;
    const int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
    int W,H,T,ans=0,v[1005][1050];
    char mp[1005][1005];
    struct data{int x,y;}st,en,P[15];
    bool check(data x){
        return(x.x&&x.y&&x.x<=H&&x.y<=W&&mp[x.x][x.y]!='X'&&v[x.x][x.y]==-1);
    }
    int bfs(data st,data en){
        queue<data> Q;
        data nx;
        for(int i=1;i<=H;i++)
            for(int j=1;j<=W;j++)v[i][j]=-1;
        Q.push(st); 
        v[st.x][st.y]=0;
        while(Q.size()){
            data px=Q.front();
            Q.pop();
            if(px.x==en.x&&px.y==en.y)break;
            for(int i=0;i<4;i++){
                nx.x=px.x+dx[i];
                nx.y=px.y+dy[i];
                if(check(nx)){
                    Q.push(nx);
                    v[nx.x][nx.y]=v[px.x][px.y]+1;
                }
            }    
        }return v[en.x][en.y];
    }
    int main(){
        scanf("%d%d%d",&H,&W,&T);
        for(int i=1;i<=H;i++)scanf("%s",mp[i]+1);
        for(int i=1;i<=H;i++)for(int j=1;j<=W;j++){
            if(mp[i][j]<='9'&&mp[i][j]>='1'){
                int c=mp[i][j]-'0';
                P[c].x=i;P[c].y=j;
            }else if(mp[i][j]=='S'){
                st.x=i;st.y=j;
            }
        }
        for(int i=1;i<=T;i++){
            en.x=P[i].x;en.y=P[i].y;
            ans+=bfs(st,en);
            st.x=en.x;st.y=en.y;
        }printf("%d
    ",ans);
        return 0;
    }

    POJ 3669:Meteor Shower

    /*
        告诉你流星砸下来的时间和砸的位置,每次流星砸下来会影响周边五个格子
        被影响到的地方将不能再通行,问能到达安全地点的最短时间
    */
    #include <cstdio>
    #include <algorithm>
    #include <climits>
    using namespace std;
    const int N=305,inf=INT_MAX; 
    int t,h,n,mp[N][N],vis[N][N],x,y,tim;
    int mx[4]={0,0,1,-1},my[4]={1,-1,0,0};
    struct data{int x,y,t;}q[N*N];
    void bfs(){
        vis[0][0]=t=h=1;
        if(mp[0][0]==inf){puts("0");return;}
        while(t<=h){
            x=q[t].x,y=q[t].y,tim=q[t++].t;
            for(int i=0;i<4;i++){
                int nx=x+mx[i],ny=y+my[i];
                if(nx<0||ny<0||vis[nx][ny]||tim+1>=mp[nx][ny])continue;
                if(mp[nx][ny]==inf){printf("%d
    ",tim+1);return;}
                q[++h].x=nx;q[h].y=ny;q[h].t=tim+1;vis[nx][ny]=1;
            }
        }puts("-1");
    }
    int main(){
        for(int i=0;i<N;i++)for(int j=0;j<N;j++)mp[i][j]=inf;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&x,&y,&tim);
            mp[x][y]=min(mp[x][y],tim);
            for(int j=0;j<4;j++){
                int nx=x+mx[j],ny=y+my[j];
                if(nx<0||ny<0)continue;
                mp[nx][ny]=min(mp[nx][ny],tim);
            }
        }return bfs(),0;
    }

    AOJ 0121:Seven Puzzle

    /*
        七数码问题,将标号1到7的块通过向空位的移动来复原
        由于操作可逆,直接通过从终态开始搜索的方法,
        将到达每种状态需要的时间记录下来
    */
    #include <queue>
    #include <iostream>
    #include <algorithm>
    #include <string>
    #include <map> 
    using namespace std;
    int dx[]={1,-1,4,-4};
    map<string,int>M;
    void bfs(){
        queue<string> Q;
        Q.push("01234567");
        M["01234567"]=1;
        while(Q.size()){
            string x=Q.front();
            Q.pop();
            int nx=0;
            for(int i=0;i<8;i++)if(x[i]=='0')nx=i;
            for(int i=0;i<4;i++){
                if(nx+dx[i]>=0&&nx+dx[i]<8){
                    if(nx==3&&i==0||nx==4&&i==1)continue;
                    string s=x;
                    swap(s[nx],s[nx+dx[i]]);
                    if(!M[s]){Q.push(s);M[s]=M[x]+1;}
                }
            }
        }
    }
    int x;
    int main(){
        bfs();
        while(cin>>x){
            string s;
            s+=x+'0';
            for(int i=1;i<8;i++)cin>>x,s+=x+'0';
            cout<<M[s]-1<<endl;
        }return 0;
    }

    POJ 2718:Smallest Difference

    /*
        给出不重复的数位,将其全部用上组成两个数,使得其差最小,
        输出这个最小差值
    */
    #include <cstdio>
    #include <algorithm>
    #include <climits>
    using namespace std;
    int a[10],n,T;
    char c;
    int main(){
        scanf("%d",&T);getchar();
        while(T--){
            for(n=0;(c=getchar())!='
    ';)if(c!=' ')a[n++]=c-'0';
            if(n==1)printf("%d
    ",a[0]);
            else if(n==2)printf("%d
    ",abs(a[1]-a[0]));
            else{
                while(a[0]==0)next_permutation(a,a+n);  
                int ans=INT_MAX,mid=(n+1)>>1;  
                do{  
                    if(a[mid]){  
                        int x=a[0],y=a[mid];  
                        for(int i=1;i<mid;i++)x=x*10+a[i];  
                        for(int i=mid+1;i<n;i++)y=y*10+a[i];  
                        if(ans>abs(x-y))ans=abs(x-y);  
                    }  
                }while(next_permutation(a,a+n));  
                printf("%d
    ",ans);  
            }
        }return 0;
    }

    POJ 3187:Backward Digit Sums

    /*
        求一个排列使得其不断地进行邻项相加,最后得到的数为给出的数字
    */
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    int a[10],b[10],n,s;
    int main(){
        scanf("%d%d",&n,&s);
        for(int i=0;i<n;i++)a[i]=i+1;
        do{
            for(int i=0;i<n;i++)b[i]=a[i];
            for(int i=n-1;i;i--){
                for(int j=0;j<i;j++)b[j]=b[j+1]+b[j];
            }
                if(b[0]==s){
                printf("%d",a[0]);
                for(int i=1;i<n;i++)printf(" %d",a[i]);
                puts(""); break;
            }
        }while(next_permutation(a,a+n));
        return 0;
    }

    AOJ 0525:Osenbei

    /*
        可以翻转行或者列,使得最终状态1最多
    */
    #include <cstdio>
    #include <algorithm>
    #include <bitset>
    using namespace std;
    int R,C,b,ans;
    bitset<10000> a[10];
    bool tmp;
    void dfs(int k){
        if(k==R){
            int tmp=0;
            for(int j=0;j<C;j++){
                int t=0;
                for(int i=0;i<R;i++)t+=a[i][j];
                tmp+=max(t,R-t);
            }ans=max(ans,tmp);
            return;
        }dfs(k+1);
        a[k].flip();
        dfs(k+1);
    }
    int main(){
        while(scanf("%d%d",&R,&C),R+C){
            for(int i=0;i<R;i++)
                for(int j=0;j<C;j++)scanf("%d",&b),a[i][j]=b; 
            ans=0;dfs(1);
            printf("%d
    ", ans);
        }return 0;
    }

    POJ 3050:Hopscotch

    /*
        求在图中任选起点随意走六步能产生的不同的序列的个数
    */
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
    int mp[1000000],a[6][6],ans=0;
    int check(int x,int y){return(x&&y&&x<6&&y<6);}
    void dfs(int x,int y,int d,int num){
        if(d==6){if(!mp[num]){mp[num]=1;ans++;}return;}
        num=num*10+a[x][y];
        for(int i=0;i<4;i++){
            int nx=x+dx[i],ny=y+dy[i];
            if(check(nx,ny))dfs(nx,ny,d+1,num);
        }
    }
    int main(){
        for(int i=1;i<=5;i++)for(int j=1;j<=5;j++)scanf("%d",&a[i][j]);
        for(int i=1;i<=5;i++)for(int j=1;j<=5;j++)dfs(i,j,0,0);
        printf("%d
    ",ans);
        return 0;
    }
    

      

  • 相关阅读:
    web项目中加斜杠与不加斜杠
    事务是什么,以及事务四个特性
    Java中 a+=b和a=a+b有什么区别?
    JAVA基础15
    JAVA基础13
    JAVA基础12
    JAVA基础11
    JAVA基础10
    DELPHI下的SOCK编程
    设置VSS2005使支持通过Internet访问(转)
  • 原文地址:https://www.cnblogs.com/forever97/p/6069065.html
Copyright © 2020-2023  润新知