UVA1601万圣节的早上

此题非常经典,确实学习到了很多的东西;

路径搜索这种类型的题目步骤是这样的:

第一保存状态

第二寻找状态之间的关系,即一个状态能够走向哪些状态

第三判断这个新产生的状态是否已经走过。

 

scanf("%d%d%d\n");后面加\N,下次读的时候就可以换行读,和fgets配合起来很好用

 

如果开数组可以把所有的状态都包含进来的话,那么就可以去开数组

 

学到的东西,只需要保存各个可以走的cell就可以了

这道题目还需要以后再细细品味一下

下面是AC代码:

#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;

const int maxn = 150;//状态个数的估计是非常重要的
struct state
{
    int fir,sec,thir;
    state(int a = 0,int b = 0,int c = 0):fir(a),sec(b),thir(c){}
};


int dist[maxn][maxn][maxn];
int start[3];
int End[3];
char G[20][20];
vector<int>Next[150];
int cnt = 0;
int dr[] = {-1,0,1,0};
int dc[] = {0,1,0,-1};
bool read_input()
{
    cnt = 0;
    memset(dist,0,sizeof(dist));
    //start.clear();
    //End.clear();
    for(int i = 0;i < 150;i++)
    {
        Next[i].clear();
    }
    int row,col,num_ghost;
    scanf("%d%d%d\n",&col,&row,&num_ghost);
    if(!row)
    {
        return false;
    }
    //cnt代表此时用多少个可以走的cell
    for(int i = 0;i < row;i++)
    {
        fgets(G[i],20,stdin);
        for(int j = 0;j < col;j++)
        {
            if(G[i][j] != '#')
            {
                if(G[i][j] <= 'Z' && G[i][j] >= 'A')
                {
                    End[G[i][j] - 'A'] = cnt;
                    //End.push_back(cnt);
                }
                else if(G[i][j] <= 'z' && G[i][j] >= 'a')
                {
                    start[G[i][j] - 'a'] = cnt;
                }
                G[i][j] = cnt;
                cnt++;
            }
        }
    }
    for(int r = 0;r < row;r++)
    {
        for(int c = 0;c < col;c++)
        {
            if(G[r][c] != '#')
            {
                Next[G[r][c]].push_back(G[r][c]);
                for(int k = 0;k < 4;k++)
                {
                    if(G[r + dr[k]][c + dc[k]] != '#')
                    {
                        Next[G[r][c]].push_back(G[r + dr[k]][c + dc[k]]);
                    }
                }
            }
        }
    }
    if(num_ghost == 1)
    {
        Next[cnt + 1].push_back(cnt + 1);
        Next[cnt + 2].push_back(cnt + 2);
        start[1] = cnt + 1;
        start[2] = cnt + 2;
        End[1] = cnt + 1;
        End[2] = cnt + 2;
        //start.push_back(cnt + 1);
        //start.push_back(cnt + 2);
    }
    else if(num_ghost == 2)
    {
        Next[cnt + 1].push_back(cnt + 1);
        start[2] = cnt + 1;
        End[2] = cnt + 1;
        //start.push_back(cnt + 1);
    }
    return 1;
}

void BFS()
{
    memset(dist,-1,sizeof(dist));
    queue<state>Q;
    state u(start[0],start[1],start[2]);
    Q.push(u);
    dist[start[0]][start[1]][start[2]] = 0;
    while(!Q.empty())
    {
        state u = Q.front();
        Q.pop();
        if(u.fir == End[0] && u.sec ==End[1] && u.thir == End[2])
        {
            printf("%d\n",dist[End[0]][End[1]][End[2]]);
            return ;//找到了答案
        }
        int fir1 ,sec1,thir1;
        for(int i = 0;i < Next[u.fir].size();i++)
        {
            fir1 = Next[u.fir][i];
            for(int j = 0; j < Next[u.sec].size();j++)
            {
                sec1 = Next[u.sec][j];
                if(fir1 == sec1 || (u.fir == sec1 && u.sec == fir1))
                    continue;
                for(int k = 0;k < Next[u.thir].size();k++)
                {
                    thir1 = Next[u.thir][k];
                    if(fir1 == thir1 || (u.fir == thir1 && u.thir == fir1))
                        continue;
                    if(sec1 == thir1 || (u.thir == sec1 && u.sec == thir1))
                        continue;
                    state v(fir1,sec1,thir1);
                    if(dist[fir1][sec1][thir1] < 0 )
                    {
                        dist[fir1][sec1][thir1] = dist[u.fir][u.sec][u.thir] + 1;
                        Q.push(v);
                    }
                }
            }
        }

    }

}

int main()
{
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    while(read_input())
    {
        BFS();
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/TorettoRui/p/10495611.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值