[kuangbin带你飞]非常可乐和Find a way

N - Find a way HDU - 2612 

Find a way

Pass a year learning in Hangzhou, yifenfei arrival hometown Ningbo at finally. Leave Ningbo one year, yifenfei have many people to meet. Especially a good friend Merceki. 
Yifenfei’s home is at the countryside, but Merceki’s home is in the center of city. So yifenfei made arrangements with Merceki to meet at a KFC. There are many KFC in Ningbo, they want to choose one that let the total time to it be most smallest. 
Now give you a Ningbo map, Both yifenfei and Merceki can move up, down ,left, right to the adjacent road by cost 11 minutes. 

INPUT

  • The input contains multiple test cases. 
  • Each test case include, first two integers n, m. (2<=n,m<=200). 
  • Next n lines, each line included m character. 
  • ‘Y’ express yifenfei initial position. 
  • ‘M’    express Merceki initial position. 
  • ‘#’ forbid road; 
  • ‘.’ Road. 
  • ‘@’ KCF 

OUTPUT

  • For each test case output the minimum total time that both yifenfei and Merceki to arrival one of KFC.You may sure there is always have a KFC that can let them meet.

测试样例

4 4
Y.#@
....
.#..
@..M
4 4
Y.#@
....
.#..
@#.M
5 5
Y..@.
.#...
.#...
@..M.
#...#

样例输出

66
88
66

题意理解:

  • 给一个定一个矩阵是地图,‘#’是墙不可通过,‘.’是路可以通过,‘@’是目的地KFC,Y和M是两人,要去KFC见面,求二人到KFC最短距离。
  • 每走一步要11分钟求最短时间。

解题思路:

这道题是迷宫的升级版,看到求最优基本排除dfs,dfs肯定会超时,选用dfs。思路没有那么高深,就是两遍dfs,分别从两给人开始dfs出两个人到KFC的距离,然后保存一下,最后选一个最短就可以了。

代码如下:

代码:

#include<iostream>
#include<queue>
#include<cstring>
#include<stdio.h>
using namespace std;

const int inf = 0x3f3f3f3f;
char mapn[1000][1000];
int visy[1000][1000];
int vism[1000][1000];
int dx[4] = {-1,1,0,0};
int dy[4] = {0,0,-1,1};
int vis[1000][1000];
int m,n;
struct point{
    int x,y;
    int countn;
};
int check(point p)
{
    if(p.x>=m||p.y>=n||p.x<0||p.y<0||mapn[p.x][p.y]=='#'||vis[p.x][p.y]==1)
        return 1;
    return 0;
}

int bfsy(int i,int j)
{
    queue<point> q;
    point p;
    p.x = i;
    p.y = j;
    p.countn = 0;
    q.push(p);
    vis[p.x][p.y] = 1;
    while(!q.empty())
    {
        point p1;
        p1 = q.front();
        //cout<<'#'<<p1.countn<<endl;
        //cout<<p1.x<<p1.y<<endl;
        q.pop();
        if(mapn[p1.x][p1.y] == '@')
        {

            visy[p1.x][p1.y] = p1.countn;
            //cout<<p1.x<<','<<p1.y<<':'<<p1.countn<<endl;
        }

        for(int k=0;k<4;k++)
        {

            point p2;
            p2.x = p1.x + dx[k];
            p2.y = p1.y + dy[k];
            p2.countn = 0;
            if(p2.countn <= p1.countn + 1)
                p2.countn = p1.countn + 1;
            if(check(p2))
                continue;

            vis[p2.x][p2.y] = 1;
            q.push(p2);
        }
    }
    return 0;
}

int bfsm(int i,int j)
{
    queue<point> q;
    point p;
    p.x = i;
    p.y = j;
    p.countn = 0;
    q.push(p);
    while(!q.empty())
    {
        point p1;
        p1 = q.front();
        q.pop();
        if(mapn[p1.x][p1.y] == '@')
        {
            vism[p1.x][p1.y] = p1.countn;
        }

        for(int k=0;k<4;k++)
        {

            point p2;
            p2.x = p1.x + dx[k];
            p2.y = p1.y + dy[k];
            p2.countn = 0;
            if(p2.countn < p1.countn + 1)
                p2.countn = p1.countn + 1;
            if(check(p2))
                continue;
            vis[p2.x][p2.y] = 1;
            q.push(p2);
        }

    }
    return 0;

}

int main()
{
    ios::sync_with_stdio(false);
    point Y,M;
    while(~scanf("%d%d",&m,&n))
    {
        memset(vism,-1,sizeof(vism));
        memset(visy,-1,sizeof(visy));

        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                cin>>mapn[i][j];
                if(mapn[i][j]=='Y')
                {
                    Y.x = i;
                    Y.y = j;
                }
                if(mapn[i][j]=='M')
                {
                    M.x = i;
                    M.y = j;
                }
            }
        }
        memset(vis,0,sizeof(vis));
        bfsy(Y.x,Y.y);
        memset(vis,0,sizeof(vis));
        bfsm(M.x,M.y);
        int minn = inf;
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(visy[i][j] > 0)
                {
                    //cout<<visy[i][j]+vism[i][j]<<endl;
                    minn = min(minn,(visy[i][j]+vism[i][j])*11);
                }

            }
        }
        cout<<minn<<endl;
    }
    return 0;
}

M - 非常可乐 HDU - 1495 

非常可乐

大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为。因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要喝的和seeyou一样多。但seeyou的手中只有两个杯子,它们的容量分别是N 毫升和M 毫升 可乐的体积为S (S<101)毫升 (正好装满一瓶) ,它们三个之间可以相互倒可乐 (都是没有刻度的,且 S==N+M,101>S>0,N>0,M>0) 。聪明的ACMER你们说他们能平分吗?如果能请输出倒可乐的最少的次数,如果不能输出"NO"。

INPUT

  • 三个整数 : S 可乐的体积 , N 和 M是两个杯子的容量,以"0 0 0"结束。

OUTPUT

  • 如果能平分的话请输出最少要倒的次数,否则输出"NO"。

测试样例

7 4 3
4 1 3
0 0 0

样例输出

NO
3

题意理解:

  • 有三个杯子容量为S、N、M,其中S = M + N。
  • 最开始S是满的,M、N均为空。
  • 输入S、M、N三个数求能不能通过来回倒可乐实现将S的可乐平分,输出最少次数或者NO。
  • 每次只能将杯中的可乐全部倒入另一个杯子中,或者将另一个杯子倒满。
  • 注意:这个题需要将可乐想成离散的,每次倒的都是整数毫升,或者把杯子想成只能是整数毫升。

解题思路:

这道题还是求最优解,所以还是一道bfs题,最开始的状态是S是满的N和M都是0,每次倒可乐有六种情况:

  1. S->N
  2. N->S
  3. S->M
  4. M->S
  5. N->M
  6. M->N

直到达到两杯中可乐相等一杯空就bfs结束,返回时间,如果到结束也没有这种情况就返回-1,然后就可以写bfs了,设一个三维数组去记录状态vis[s][n][m]设一个count去计数,我得做法是写一个结构体,有四个参数s、n、m和countn计数,

不会写的可以参考这篇文章:https://blog.csdn.net/qq_31267769/article/details/88782954

代码如下:

代码:

#include<iostream>
#include<stdio.h>
#include<queue>
#include<cstring>

using namespace std;

int vis[101][101][101];

struct node{
    int s;
    int n;
    int m;
    int countn;
};

int verify(int i,int j,int k,int s)
{
    if((i==j&&i==s/2)||(i==k&&i==s/2)||(j==k&&j==s/2))
        return 1;
    return 0;
}

int bfs(int s,int n,int m)
{
    if(s % 2 == 1)///奇数无法平分
        return -1;
    queue<node> q;
    node Node;
    Node.s = s;
    Node.n = 0;
    Node.m = 0;
    Node.countn = 0;
    q.push(Node);
    while(!q.empty())
    {
        node n1 = q.front();
        q.pop();
        ///s->n
        node n2;
        if(verify(n1.s,n1.n,n1.m,s))
            return n1.countn;
        if(n1.s>0&&n-n1.n>0)
        {
            int muchn = n-n1.n;
            //int mushs = s-n1.s;
            if(n1.s>=muchn)
            {
                n2.s = n1.s-muchn;
                n2.n = n;
                n2.m = n1.m;
            }
            else
            {
                n2.s = 0;
                n2.n = n1.n+n1.s;
                n2.m = n1.m;
            }
            if(vis[n2.s][n2.n][n2.m] == 0)
            {
                vis[n2.s][n2.n][n2.m] = 1;
                n2.countn = n1.countn+1;
                q.push(n2);
            }
        }
        ///n->s
        if(n1.n>0&&s-n1.s>0)
        {
            //int muchn = n-n1.n;
            int muchs = s-n1.s;
            if(n1.n>=muchs)
            {
                n2.n = n1.n-muchs;
                n2.s = s;
                n2.m = n1.m;
            }
            else
            {
                n2.n = 0;
                n2.s = n1.s+n1.n;
                n2.m = n1.m;
            }
            if(vis[n2.s][n2.n][n2.m] == 0)
            {
                vis[n2.s][n2.n][n2.m] = 1;
                n2.countn = n1.countn+1;
                q.push(n2);
            }
        }
        ///s->m
        if(n1.s>0&&m-n1.m>0)
        {
            int muchm = m-n1.m;
            //int mushs = s-n1.s;
            if(n1.s>=muchm)
            {
                n2.s = n1.s-muchm;
                n2.m = m;
                n2.n = n1.n;
            }
            else
            {
                n2.s = 0;
                n2.m = n1.m+n1.s;
                n2.n = n1.n;
            }
            if(vis[n2.s][n2.n][n2.m] == 0)
            {
                vis[n2.s][n2.n][n2.m] = 1;
                n2.countn = n1.countn+1;
                q.push(n2);
            }
        }
        ///m->s
        if(n1.m>0&&s-n1.s>0)
        {
            //int muchn = n-n1.n;
            int muchs = s-n1.s;
            if(n1.m>=muchs)
            {
                n2.m = n1.m-muchs;
                n2.s = s;
                n2.n = n1.n;
            }
            else
            {
                n2.m = 0;
                n2.s = n1.s+n1.m;
                n2.n = n1.n;
            }
            if(vis[n2.s][n2.n][n2.m] == 0)
            {
                vis[n2.s][n2.n][n2.m] = 1;
                n2.countn = n1.countn+1;
                q.push(n2);
            }
        }
        ///n->m
        if(n1.n>0&&m-n1.m>0)
        {
            int muchm = m-n1.m;
            //int mushs = s-n1.s;
            if(n1.n>=muchm)
            {
                n2.n = n1.n-muchm;
                n2.m = m;
                n2.s = n1.s;
            }
            else
            {
                n2.n = 0;
                n2.m = n1.m+n1.n;
                n2.s = n1.s;
            }
            if(vis[n2.s][n2.n][n2.m] == 0)
            {
                vis[n2.s][n2.n][n2.m] = 1;
                n2.countn = n1.countn+1;
                q.push(n2);
            }
        }
        ///m->n
        if(n1.m>0&&n-n1.n>0)
        {
            //int muchn = n-n1.n;
            int muchn = n-n1.n;
            if(n1.m>=muchn)
            {
                n2.m = n1.m-muchn;
                n2.n = n;
                n2.s = n1.s;
            }
            else
            {
                n2.m = 0;
                n2.n = n1.n+n1.m;
                n2.s = n1.s;
            }
            if(vis[n2.s][n2.n][n2.m] == 0)
            {
                vis[n2.s][n2.n][n2.m] = 1;
                n2.countn = n1.countn+1;
                q.push(n2);
            }
        }
    }
    return -1;
}


int main()
{



    int s,n,m;
    while(scanf("%d%d%d",&s,&n,&m) != EOF)
    {
        memset(vis,0,sizeof(vis));
        vis[s][0][0] = 1;
        if(n==0&&m==0&&s==0)
            break;
        int ans = bfs(s,n,m);
        if(ans <0)
            cout<<"NO"<<endl;
        else
            cout<<ans<<endl;
    }
    return 0;
}

总结:

写bfs就是十分的长(可能我写的不是专业选手的写法)。

还有就是一定要

打标记!!!

不然内存会爆!!!

多组输入数据的时候一定要记得

清空标记!!!

不然这bug不注意能调一天

血一样的教训,这两个题都是,多组数据之间忘了清空标记了,怎么改都不对。。。断断续续改了有一整天。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值