[kuangbin帶你飛]專題一 簡單搜索

專題連接:https://cn.vjudge.net/contest/65959

 

A - 棋盤問題

題意:在棋盤上放k個棋子的方案數。要求每行每列至多隻有一個。

思路:DFS。詳見代碼。

#include <cstdio>
using namespace std; char m[10][10]; int n,k; int ans; void dfs(int x,int y,int num) { if(num==k) { ans++; return; } while(x<=n) { if(m[x][y]=='#') { int flag=1; for(int j=1;j<=n;j++) if(m[j][y]=='*'||m[x][j]=='*') flag=0; if(flag==1) { m[x][y]='*'; dfs(x,y,num+1); m[x][y]='#'; } } y++; if(y>n) { y=1; x++; } } } int main() { while(~scanf("%d%d",&n,&k)) { if(n==-1&&k==-1) break; for(int i=1;i<=n;i++) scanf("%s",m[i]+1); ans=0; dfs(1,1,0); printf("%d\n",ans); } return 0; }

 

B - Dungeon Master

題意:三維走迷宮問題。

思路:BFS,注意邊界判斷,詳見代碼。

#include <cstdio> #include <queue> #include <cstring> #include <iostream>
using namespace std; const int INF=0x3f3f3f3f; char m[40][40][40]; bool use[40][40][40]; int dirx[6]={0,0,0,0,1,-1}; int diry[6]={0,0,1,-1,0,0}; int dirz[6]={1,-1,0,0,0,0}; int l,r,c,ans; struct node { int x;//r
    int y;//c
    int z;//l
    int num; }s,t; void bfs() { queue<node >q; q.push(s); while(!q.empty()) { node now=q.front(); q.pop(); use[now.x][now.y][now.z]=1; if(now.x==t.x&&now.y==t.y&&now.z==t.z) ans=min(ans,now.num); else
            for(int i=0;i<6;i++) { if(now.x+dirx[i]<1||now.x+dirx[i]>r) continue; if(now.y+diry[i]<1||now.y+diry[i]>c) continue; if(now.z+dirz[i]<1||now.z+dirz[i]>l) continue; node next; next.x=now.x+dirx[i]; next.y=now.y+diry[i]; next.z=now.z+dirz[i]; next.num=now.num+1; if(m[next.x][next.y][next.z]!='#'&&use[next.x][next.y][next.z]==0) { q.push(next); use[next.x][next.y][next.z]=1; } } } } int main() { while(scanf("%d%d%d",&l,&r,&c)!=EOF) { if(l==0&&r==0&&c==0) break; for(int i=1;i<=l;i++) { for(int j=1;j<=r;j++) { getchar(); for(int k=1;k<=c;k++) { scanf("%c",&m[j][k][i]); if(m[j][k][i]=='S') s.x=j,s.y=k,s.z=i,s.num=0; else if(m[j][k][i]=='E') t.x=j,t.y=k,t.z=i; } } getchar(); } memset(use,0,sizeof(use)); ans=INF; bfs(); if(ans==INF) printf("Trapped!\n"); else printf("Escaped in %d minute(s).\n",ans); } return 0; }B

 

C - Catch That Cow

題意:一維數軸上從n點到k的最短用時。三種移動操做:n+1,n-1,n*2.

思路:BFS問題,從起點開始三個方向進行搜索,注意邊界判斷,具體看代碼。

#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <algorithm> #include <cmath>
using namespace std; const int INF=0x3f3f3f3f; int use[200100]; struct node { int x; int num; }; int ans; int n,k; int bfs(int nows) { use[nows]=1; queue<node>q; while(!q.empty()) q.pop(); node s; s.x=nows,s.num=0; q.push(s); while(!q.empty()) { node now=q.front(); q.pop(); if(now.x==k) return now.num; if(now.x+1<=100000&&use[now.x+1]==0) { use[now.x+1]=1; node next; next.num=now.num+1; next.x=now.x+1; q.push(next); } if(now.x-1>=0&&now.x-1<=100000&&use[now.x-1]==0) { use[now.x-1]=1; node next; next.num=now.num+1; next.x=now.x-1; q.push(next); } if(now.x*2>=0&&now.x*2<=100000&&use[now.x*2]==0) { use[now.x*2]=1; node next; next.num = now.num + 1; next.x = now.x * 2; q.push(next); } } } int main() { while(~scanf("%d%d",&n,&k)) { memset(use,0,sizeof(use)); ans=bfs(n); printf("%d\n",ans); } return 0; }

 

D - Fliptile

題意:一個M×N的棋盤,0表示白色,1表示黑色,每次翻轉一個棋子及其相鄰的棋子。問可否將棋盤翻轉爲全白。若是能夠輸出翻轉矩陣。

思路:枚舉第一行的翻轉狀況。由於N<=15。最多有2^15次種狀況。對每種狀況進行搜索,先翻轉第一行棋子,而後遍歷第二行開始的全部棋子,當前棋子上面的棋子若爲黑,則必須翻轉當前棋子。

最後判斷最後一行是否全白。記錄翻轉最小次數。具體看代碼。

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int INF=0x3f3f3f3f;
int m,n;
int dirx[4]={0,0,-1,1};
int diry[4]={1,-1,0,0};
int mp[20][20];
int lsmp[20][20];
int ans[20][20];
int lsans[20][20];
int num,lsnum;
void f(int x,int y) {
    lsans[x][y]=1;
    lsmp[x][y]=1-lsmp[x][y];
    for(int i=0;i<4;i++)
        if(x+dirx[i]>=1&&x+dirx[i]<=m&&y+diry[i]>=1&&y+diry[i]<=n)
            lsmp[x+dirx[i]][y+diry[i]]=1-lsmp[x+dirx[i]][y+diry[i]];
}
void dfs() {
    lsnum=0;
    for(int i=1;i<=n;i++)
        if(lsans[1][i]==1) {
            f(1,i);
            lsnum++;
        }
    for(int i=2;i<=m;i++)
        for(int j=1;j<=n;j++)
            if(lsmp[i-1][j]==1) {
                f(i,j);
                lsnum++;
            }
    int flag=1;
        for(int j=1;j<=n;j++)
            if(lsmp[m][j]==1) flag=0;
    if(flag==1) {
        if(lsnum<num) {
            num=lsnum;
            for(int i=1;i<=m;i++)
                for(int j=1;j<=n;j++)
                    ans[i][j]=lsans[i][j];
        }
    }
}
int main()
{
    while(cin>>m>>n) {
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
                scanf("%d",&mp[i][j]);
        num=INF;
        for(int k=0;k<(1<<(n));k++)
        {
            memset(lsans,0, sizeof(lsans));
            for(int i=1;i<=m;i++)
                for(int j=1;j<=n;j++)
                    lsmp[i][j]=mp[i][j];
            for(int j=1;j<=n;j++) {
                if(k&(1<<(j-1)))
                    lsans[1][j]=1;
            }

            dfs();
        }
        if(num==INF) printf("IMPOSSIBLE\n");
        else
        {
            
            for (int i = 1; i <= m; i++) {
                for (int j = 1; j <= n; j++)
                    if (j != n) printf("%d ", ans[i][j]);
                    else printf("%d\n", ans[i][j]);

            }
        }
    }
}

 

 E - Find The Multiple

題意:中文題,很少說。

思路:首先注意到全部m確定是一個小的m×10或者m×10+1獲得的。那麼咱們能夠從n開始枚舉m,直到找到知足要求(m%n==0)的解。實際上最大的m也不會超過long long 。具體看代碼。

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
typedef long long int ll;
const int INF=0x3f3f3f3f;
int n;
void bfs()
{
    queue<ll> q;
    q.push(1);
    while(!q.empty())
    {
        ll now=q.front();
        q.pop();
        if(now%n==0)
        {
            cout<<now<<endl;
            return ;
        }
        q.push(now*10);
        q.push(now*10+1);
    }

}
int main()
{
    while(scanf("%d",&n)&&n)
    {
        bfs();
    }
    return 0;
}

 

F - Prime Path

題意:給出四位數的質數n,m。要求每次變換某一位上的數字且每次變換後的數也是質數,求從n到m的最小變換次數。

思路:n和m都只有四位,預處理出質數,直接BFS便可。具體看代碼。

 

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int INF=0x3f3f3f3f;
bool flag[10010];
bool visit[10010];
int t,n,m;
struct node
{
    int x;
    int step;
};
void init()
{
    flag[0]=flag[1]=1;
    for(int i=2;i<=10000;i++)
        if(flag[i]==0)
        {
            for(int j=i*2;j<=10000;j+=i)
                flag[j]=1;
        }
}
int power(int x,int t)
{
    int ans=1;
    for(int i=1;i<=t;i++)
        ans*=x;
    return ans;
}
void bfs(int n,int m)
{
    memset(visit,0, sizeof(visit));
    node now;
    visit[n]=1;
    now.x=n,now.step=0;
    queue<node>q;
    q.push(now);
    while(!q.empty())
    {
        node temp=q.front();q.pop();
        if(temp.x==m)
        {
            printf("%d\n",temp.step);
            return ;
        }
        int num[5];
        int nowx=temp.x;
        num[4]=nowx%10;nowx/=10;
        num[3]=nowx%10;nowx/=10;
        num[2]=nowx%10;nowx/=10;
        num[1]=nowx%10;nowx/=10;
        for(int i=1;i<=4;i++)
            for(int j=0;j<=9;j++)
            {
                if(i==1&&j==0) continue;
                if(num[i]==j) continue;
                if(i==4&&j==0) continue;
                int nown=temp.x;
                nown=nown-num[i]*power(10,4-i)+j*power(10,4-i);
                if(flag[nown]==0&&visit[nown]==0)
                {
                    visit[nown]=1;
                    node next;
                    next.x=nown;
                    next.step=temp.step+1;
                    q.push(next);
                }



            }

    }
    printf("Impossible\n");
}
int main()
{
    init();
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        if(n==m) cout<<"0"<<endl;
        else bfs(n,m);
    }
}

 

 G - Shuffle'm Up

題意:給出字符串長度C,兩個長度爲C的字符串a,b 一個長度爲2C的字符串c。每次操做依次輪流從b和a取出字符組成新的字符串d。若是d!=c,將d前半部分給a,後半部分給把,問須要幾回操做能夠獲得C。若是不能輸出-1。

思路:雖然放在搜索裏,實際上是個模擬吧。照着作就好了。注意若是操做次數超過了2C就永遠不能組成了。具體看代碼。

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int INF=0x3f3f3f3f;
bool flag[10010];
bool visit[10010];
int T,C;
string a,b,c;
int main()
{
    cin>>T;
    int cases=1;
    while(T--)
    {
        cin>>C;
        cin>>a>>b>>c;
        if(a+b==c) printf("%d 0\n",cases++);
        else
        {
            int num=0;
            int flag=0;
            while(num<=2*C)
            {
                num++;
                string d="";
                for(int i=0;i<C;i++)
                    d=d+b[i]+a[i];
                if(d==c)
                {
                    flag=1;break;
                }
                a="";
                for(int i=0;i<C;i++)
                    a+=d[i];
                b="";
                for(int i=0;i<C;i++)
                    b+=d[C+i];
            }
            if(flag==0) printf("%d -1\n",cases++);
            else printf("%d %d\n",cases++,num);

        }
    }
}

 

H - Pots

題意:有容量爲a,b兩個容器,問可否經過三種操做(倒滿某個容器,倒空某個容器,將一個容器的水倒入另外一個容器)獲得容量C。輸出最小操做數和操做過程或者impossible。

思路:由於a,b<100,直接6方向BFS便可。能夠將操做過程在BFS過程同時更新。具體看代碼。

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int INF=0x3f3f3f3f;
bool use[110][110];
int aa,bb,cc;
struct caozuo
{
    int num;
    int from;
    int to;
};

struct node
{
    int a;
    int b;
    int step;
    vector<caozuo> v;
};
void bfs()
{
    //temlist.assign(list.begin(), list.end());
    node now;
    now.a=0;
    now.b=0;
    memset(use,0, sizeof(use));
    use[0][0]=1;
    now.v.clear();
    now.step=0;
    queue<node >q;
    q.push(now);
    while(!q.empty())
    {
        node temp=q.front();q.pop();
        if(temp.a==cc||temp.b==cc)
        {
            printf("%d\n",temp.step);
            for(int i=0;i<temp.v.size();i++)
            {
                caozuo now=temp.v[i];
                if(now.num==1)
                {
                    if(now.from==1) printf("FILL(1)\n");
                    else printf("FILL(2)\n");
                }
                else  if(now.num==2)
                {
                    if(now.from==1) printf("DROP(1)\n");
                    else printf("DROP(2)\n");
                }
                else if(now.num==3)
                {
                    if(now.from==1) printf("POUR(1,2)\n");
                    else printf("POUR(2,1)\n");
                }
            }
            return ;
        }
        if(temp.a!=aa&&use[aa][temp.b]==0)//a-fill
        {
            use[aa][temp.b]=1;
            node next;
            next.a=aa;
            next.b=temp.b;
            next.step=temp.step+1;
            next.v.assign(temp.v.begin(),temp.v.end());
            caozuo next1;
            next1.num=1;
            next1.from=1;
            next.v.push_back(next1);
            q.push(next);
        }
        if(temp.b!=bb&&use[temp.a][bb]==0)//b-fill
        {
            use[temp.a][bb]=1;
            node next;
            next.a=temp.a;
            next.b=bb;
            next.step=temp.step+1;
            next.v.assign(temp.v.begin(),temp.v.end());
            caozuo next1;
            next1.num=1;
            next1.from=2;
            next.v.push_back(next1);
            q.push(next);
        }
        if(temp.a!=0&&use[0][temp.b]==0)//a-0
        {
            use[0][temp.b]=1;
            node next;
            next.a=0;
            next.b=temp.b;
            next.step=temp.step+1;
            next.v.assign(temp.v.begin(),temp.v.end());
            caozuo next1;
            next1.num=2;
            next1.from=1;
            next.v.push_back(next1);
            q.push(next);
        }
        if(temp.b!=0&&use[temp.a][0]==0)//b-0
        {
            use[temp.a][0]=1;
            node next;
            next.a=temp.a;
            next.b=0;
            next.step=temp.step+1;
            next.v.assign(temp.v.begin(),temp.v.end());
            caozuo next1;
            next1.num=2;
            next1.from=2;
            next.v.push_back(next1);
            q.push(next);
        }

        if(temp.a!=0&&temp.b!=bb)//a-b
        {
            if(temp.a+temp.b<=bb&&use[0][temp.a+temp.b]==0) {
                use[0][temp.a+temp.b] = 1;
                node next;
                next.a = 0;
                next.b = temp.a+temp.b;
                next.step = temp.step + 1;
                next.v.assign(temp.v.begin(), temp.v.end());
                caozuo next1;
                next1.num=3;
                next1.from=1;
                next1.to=2;
                next.v.push_back(next1);
                q.push(next);
            }
            else if(temp.a+temp.b>bb&&use[temp.a+temp.b-bb][bb]==0) {
                use[temp.a+temp.b-bb][bb] = 1;
                node next;
                next.a = temp.a+temp.b-bb;
                next.b = bb;
                next.step = temp.step + 1;
                next.v.assign(temp.v.begin(), temp.v.end());
                caozuo next1;
                next1.num = 3;
                next1.from = 1;
                next1.to=2;
                next.v.push_back(next1);
                q.push(next);
            }
        }
        if(temp.b!=0&&temp.a!=aa)//b-a
        {
            if(temp.a+temp.b<=aa&&use[temp.a+temp.b][0]==0) {
                use[temp.a+temp.b][0] = 1;
                node next;
                next.a = temp.a+temp.b;
                next.b = 0;
                next.step = temp.step + 1;
                next.v.assign(temp.v.begin(), temp.v.end());
                caozuo next1;
                next1.num=3;
                next1.from=2;
                next1.to=1;
                next.v.push_back(next1);
                q.push(next);
            }
            else if(temp.a+temp.b>aa&&use[aa][temp.a+temp.b-aa]==0) {
                use[aa][temp.a+temp.b-aa] = 1;
                node next;
                next.a = aa;
                next.b = temp.a+temp.b-aa;
                next.step = temp.step + 1;
                next.v.assign(temp.v.begin(), temp.v.end());
                caozuo next1;
                next1.num=3;
                next1.from=2;
                next1.to=1;
                next.v.push_back(next1);
                q.push(next);
            }
        }
    }
    printf("impossible\n");

}
int main()
{
    while(cin>>aa>>bb>>cc)
    {
        bfs();
    }
}

 

I - Fire Game(http://acm.fzu.edu.cn/problem.php?pid=2150)

題意:'#'能夠燃燒,'.'不能夠燃燒。選擇兩個#點(能夠重複)放火,每過一秒能夠向四個方向燃燒,問可否所有燒光全部的#,若是能夠給出燒光的最少時間。

思路:注意到數據規模很小,咱們能夠暴力枚舉兩個#點。初始化到達每一個#的時間爲INF。作兩遍BFS,到達每一個#的時間爲兩遍BFS裏短的時間。每一種狀況所需的時間爲全部#的最長到達時間。最後取全部最長時間的最小值。具體看代碼。能夠用雙向BFS優化爲一次BFS。

#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <algorithm> #include <set>
using namespace std; const int INF=0x3f3f3f3f; int m,n; int dirx[4]={0,0,-1,1}; int diry[4]={1,-1,0,0}; char mp[15][15]; int lsans[15][15],ans; struct node { int x; int y; int step; }; bool use[15][15]; void  bfs(int xx,int yy) { memset(use,0,sizeof(use)); queue<node >q; node now; now.x=xx,now.y=yy,now.step=0; use[xx][yy]=1; q.push(now); while(!q.empty()) { node now=q.front(); lsans[now.x][now.y]=min( lsans[now.x][now.y],now.step); q.pop(); for(int i=0;i<4;i++) { node next; next.x=now.x+dirx[i]; next.y=now.y+diry[i]; next.step=now.step+1; if(use[next.x][next.y]==1) continue; if(next.x>=1&&next.x<=n&&next.y>=1&&next.y<=m) if(mp[next.x][next.y]=='#') { use[next.x][next.y]=1; q.push(next); } } } } int main() { int t; int cas=1; scanf("%d",&t); while(t--) { ans=0; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%s",mp[i]+1); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(mp[i][j]=='#') ans=INF; for(int i=1;i<=n*m;i++) { int nx=i/m+1,ny=i%m; if(ny==0) nx--,ny=m; if(mp[nx][ny]!='#') continue; for(int j=i;j<=n*m;j++) { int nnx=j/m+1,nny=j%m; if(nny==0) nnx--,nny=m; if(mp[nnx][nny]=='#') { memset(lsans,INF,sizeof(lsans)); bfs(nx,ny); bfs(nnx,nny); int lsnum=0; for(int k=1;k<=n;k++) for(int p=1;p<=m;p++) if(mp[k][p]=='#') lsnum=max(lsnum,lsans[k][p]); ans=min(ans,lsnum); } } } if(ans!=INF) printf("Case %d: %d\n",cas++,ans); else printf("Case %d: -1\n",cas++); } }

 

J - Fire!

題意:F的位置是火,J的位置是人。詢問人是否能夠逃出迷宮,若是能夠求逃出迷宮的時間。注意起火點不必定只有一個。

思路:先作一次BFS求出每一個點的起火時間,再作一遍BFS判斷可否逃出。具體看代碼。

#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <algorithm> #include <set>
using namespace std; const int INF=0x3f3f3f3f; const int MAXN=1010; int n,m; struct node { char p; int fire; int peo; int x; int y; }mp[MAXN][MAXN]; int jx,jy,ans; bool use[1010][1010]; int dirx[4]={0,0,1,-1}; int diry[4]={1,-1,0,0}; void dfs1() { queue<node >q; memset(use,0, sizeof(use)); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { if(mp[i][j].p=='F') { mp[i][j].fire=0; q.push(mp[i][j]); } } while(!q.empty()) { node now=q.front(); q.pop(); for(int i=0;i<4;i++) { if(now.x+dirx[i]>=1&&now.x+dirx[i]<=n&&now.y+diry[i]>=1&&now.y+diry[i]<=m) if(use[now.x+dirx[i]][now.y+diry[i]]==0) if(mp[now.x+dirx[i]][now.y+diry[i]].p=='.') { use[now.x+dirx[i]][now.y+diry[i]]=1; mp[now.x+dirx[i]][now.y+diry[i]].fire=now.fire+1; q.push(mp[now.x+dirx[i]][now.y+diry[i]]); } } } } void dfs2() { mp[jx][jy].peo=0; queue<node >q; q.push(mp[jx][jy]); memset(use,0, sizeof(use)); use[jx][jy]=1; while(!q.empty()) { node now=q.front(); q.pop(); if(now.x==0||now.x==n+1||now.y==0||now.y==m+1) ans=min(ans,now.peo); for(int i=0;i<4;i++) { if(now.x+dirx[i]>=0&&now.x+dirx[i]<=n+1&&now.y+diry[i]>=0&&now.y+diry[i]<=m+1) if(use[now.x+dirx[i]][now.y+diry[i]]==0) if(now.x+dirx[i]==0||now.x+dirx[i]==n+1||now.y+diry[i]==0||now.y+diry[i]==m+1||mp[now.x+dirx[i]][now.y+diry[i]].p=='.') if(now.x+dirx[i]==0||now.x+dirx[i]==n+1||now.y+diry[i]==0||now.y+diry[i]==m+1||now.peo+1<mp[now.x+dirx[i]][now.y+diry[i]].fire) { use[now.x+dirx[i]][now.y+diry[i]]=1; mp[now.x+dirx[i]][now.y+diry[i]].peo=now.peo+1; q.push(mp[now.x+dirx[i]][now.y+diry[i]]); } } } } int main() { int t; int cas=1; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { getchar(); for(int j=1;j<=m;j++) { scanf("%c",&mp[i][j].p); if(mp[i][j].p=='J') { jx=i; jy=j; } } } for(int i=0;i<=n+1;i++) for(int j=0;j<=m+1;j++) mp[i][j].x=i,mp[i][j].y=j,mp[i][j].peo=mp[i][j].fire=INF; ans=INF; dfs1(); dfs2(); if(ans!=INF) cout<<ans<<endl; else cout<<"IMPOSSIBLE"<<endl; } }

 

K - 迷宮問題

題意:5×5的地圖,0能夠走,1不能夠走。求從左上角走到有右下角的惟一最短路徑。要求輸出路徑。

思路:BFS。路徑能夠保存在每一次的狀態裏。具體看代碼。

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int INF=0x3f3f3f3f;
int visit[10][10];
int mp[10][10];
int dirx[4]={0,0,1,-1};
int diry[4]={1,-1,0,0};
struct road
{
    int x;
    int y;
};
struct node
{
    int nx;
    int ny;
    vector<road>v;

};
void bfs()
{
    node now;
    road now1;
    now1.x=1,now1.y=1;
    now.v.push_back(now1);
    now.nx=1,now.ny=1;
    memset(visit,0, sizeof(visit));
    visit[1][1]=1;
    queue<node >q;
    q.push(now);
    while(!q.empty())
    {
        node temp=q.front();
        q.pop();
        if(temp.nx==5&&temp.ny==5)
        {
            int num=temp.v.size();
            for(int i=0;i<num;i++)
            {
                printf("(%d, %d)\n",temp.v[i].x-1,temp.v[i].y-1);
            }
            return ;
        }
        for(int i=0;i<4;i++)
        {
            node next;
            next.nx=temp.nx+dirx[i];
            next.ny=temp.ny+diry[i];
            next.v.assign(temp.v.begin(),temp.v.end());
            road next1;
            next1.x=next.nx;
            next1.y=next.ny;
            next.v.push_back(next1);
            if(next.nx>=1&&next.nx<=5&&next.ny>=1&&next.ny<=5)
                if(visit[next.nx][next.ny]==0&&mp[next.nx][next.ny]==0)
                {
                    visit[next.nx][next.ny]=1;
                    q.push(next);
                }
        }
    }


}
int main()
{
    for(int i=1;i<=5;i++)
        for(int j=1;j<=5;j++)
            cin>>mp[i][j];
    bfs();
}

 

L - Oil Deposits

題意:求聯通塊數,注意斜對角也算聯通。

思路:DFS 每次選擇'@'點,將與之聯通的設爲'.',DFS的次數就是聯通塊數。

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=110;
int n,m;
char mp[MAXN][MAXN];
int dirx[8]={1,-1,0,0,1,1,-1,-1};
int diry[8]={0,0,1,-1,1,-1,1,-1};
int ans;
void dfs(int x,int y)
{
      mp[x][y]='*';
      for(int i=0;i<8;i++)
      {
          int nx=x+dirx[i];
          int ny=y+diry[i];
          if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&mp[nx][ny]=='@') dfs(nx,ny);
      }
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0) break;
        for(int i=1;i<=n;i++)
        {
            scanf("%s",mp[i]+1);
        }
        ans=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(mp[i][j]=='@')
                {
                    ans++;
                    dfs(i,j);
                }
        printf("%d\n",ans);
    }

}

 

M - 很是可樂(HDOJ1495)

題意:給你一瓶容量爲S的可樂和兩個容量分別爲N、M的杯子。詢問最少能平分可樂的次數。若是不能輸出NO。

思路:能夠當作是一個有六個方向的BFS。六個方向:s->n,s->m,n->s,n->m,n->m,m->n 具體看代碼。

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int INF=0x3f3f3f3f;
int nn,mm,ss;
bool use[110][110];
struct node
{
    int n;
    int m;
    int s;
    int t;
};
int  bfs()
{
     node now;
     now.n=0,now.m=0,now.s=ss,now.t=0;
     memset(use,0,sizeof(use));
     use[0][0]=1;
     queue<node>q;
     q.push(now);
     while(!q.empty())
     {
         node now=q.front();
         q.pop();
         if(now.n==ss/2&&now.s==ss/2) return  now.t;
         if(now.n<nn)//s->n
         {
             int nextn=nn;
             int nextm=now.m;
             int nexts=now.n+now.s-nn;
             if(use[nextn][nextm]==0)
             {
                 use[nextn][nextm]=1;
                 node next;
                 next.m=nextm;
                 next.n=nextn;
                 next.s=nexts;
                 next.t=now.t+1;
                 q.push(next);
             }
         }
         if(now.m<mm)//s->m
         {
             int nextn=now.n;
             int nextm=mm;
             int nexts=now.m+now.s-mm;
             if(use[nextn][nextm]==0)
             {
                 use[nextn][nextm]=1;
                 node next;
                 next.m=nextm;
                 next.n=nextn;
                 next.s=nexts;
                 next.t=now.t+1;
                 q.push(next);
             }
         }
         if(now.n>0)//n->s
         {
             int nextn=0;
             int nextm=now.m;
             int nexts=now.n+now.s;
             if(use[nextn][nextm]==0)
             {
                 use[nextn][nextm]=1;
                 node next;
                 next.m=nextm;
                 next.n=nextn;
                 next.s=nexts;
                 next.t=now.t+1;
                 q.push(next);
             }
         }
         if(now.m>0)//m->s
         {
             int nextn=now.n;
             int nextm=0;
             int nexts=now.m+now.s;
             if(use[nextn][nextm]==0)
             {
                 use[nextn][nextm]=1;
                 node next;
                 next.m=nextm;
                 next.n=nextn;
                 next.s=nexts;
                 next.t=now.t+1;
                 q.push(next);
             }
         }
         if(now.m>0&&now.n<nn)//m->n
         {
             int nextn,nextm,nexts;
             if(now.m+now.n<=nn)
             {
                 nextm=0;
                 nextn=now.m+now.n;
                 nexts=now.s;
             }
             else
             {
                 nextm=now.m+now.n-nn;
                 nextn=nn;
                 nexts=now.s;
             }
             if(use[nextn][nextm]==0)
             {
                 use[nextn][nextm]=1;
                 node next;
                 next.m=nextm;
                 next.n=nextn;
                 next.s=nexts;
                 next.t=now.t+1;
                 q.push(next);
             }
         }
         if(now.n>0&&now.m<mm)//n->m
         {
             int nextn,nextm,nexts;
             if(now.n+now.m<=mm)
             {
                 nextm=now.m+now.n;
                 nextn=0;
                 nexts=now.s;
             }
             else
             {
                 nextm=mm;
                 nextn=now.n+now.m-mm;
                 nexts=now.s;
             }
             if(use[nextn][nextm]==0)
             {
                 use[nextn][nextm]=1;
                 node next;
                 next.m=nextm;
                 next.n=nextn;
                 next.s=nexts;
                 next.t=now.t+1;
                 q.push(next);
             }
         }

     }
     return 0;
}
int main()
{
    while(~scanf("%d%d%d",&ss,&nn,&mm))
    {
        if(nn==0&&mm==0&&ss==0) break;
        if(nn<mm) swap(nn,mm);
        if(ss%2==1)
            printf("NO\n");
        else
        {
            int ans=bfs();
            if(ans==0)  printf("NO\n");
            else printf("%d\n",ans);
        }
    }

}

 

N - Find a way(HDOJ2612)

題意:求兩我的到全部KFC的時間和的最小值。

思路:2次BFS求出兩我的分別到每一個KFC的時間。最後選擇和的最小值。具體看代碼。

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int INF=0x3f3f3f3f;
int n,m;
char mp[210][210];
bool use[210][210];
int ans1[210][210];
int ans2[210][210];
int dirx[4]={0,0,1,-1};
int diry[4]={1,-1,0,0};
struct node
{
    int x;
    int y;
    int t;
};
void   bfs1()
{
    memset(use,0,sizeof(use));
    memset(ans1,INF,sizeof(ans1));
    node now;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(mp[i][j]=='Y')
            {
                now.x=i;
                now.y=j;
                break;
            }
    now.t=0;
    use[now.x][now.y]=1;
    queue<node >q;
    q.push(now);
    while(!q.empty())
    {
        node now=q.front();
        if(mp[now.x][now.y]=='@')
            ans1[now.x][now.y]=now.t;
        q.pop();
        for(int i=0;i<4;i++)
        {
            node next;
            next.x=now.x+dirx[i];
            next.y=now.y+diry[i];
            next.t=now.t+1;
            if(next.x>=1&&next.x<=n&&next.y>=1&&next.y<=m)
                if(mp[next.x][next.y]!='#')
                    if(use[next.x][next.y]==0)
                    {
                        use[next.x][next.y]=1;
                        q.push(next);
                    }
        }
    }

}
void bfs2()
{
    memset(use,0, sizeof(use));
    memset(ans2,INF,sizeof(ans2));
    node now;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(mp[i][j]=='M')
            {
                now.x=i;
                now.y=j;
                break;
            }
    now.t=0;
    use[now.x][now.y]=1;
    queue<node >q;
    q.push(now);
    while(!q.empty())
    {
        node now=q.front();
        if(mp[now.x][now.y]=='@')
            ans2[now.x][now.y]=now.t;
        q.pop();
        for(int i=0;i<4;i++)
        {
            node next;
            next.x=now.x+dirx[i];
            next.y=now.y+diry[i];
            next.t=now.t+1;
            if(next.x>=1&&next.x<=n&&next.y>=1&&next.y<=m)
                if(mp[next.x][next.y]!='#')
                    if(use[next.x][next.y]==0)
                    {
                        use[next.x][next.y]=1;
                        q.push(next);
                    }
        }
    }
}
void solve()
{
    int ans=INF;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(mp[i][j]=='@')
                ans=min(ans,ans1[i][j]+ans2[i][j]);
    printf("%d\n",ans*11);
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1;i<=n;i++)
            scanf("%s",mp[i]+1);
        bfs1();
        bfs2();
        solve();
    }

}
相關文章
相關標籤/搜索