3.17——3.19学习总结

https://vjudge.net/contest/547627#problem/J

题解:找到所有可行的路径,所以是一道深搜题目

1.输出可能的结束条件:有二十个城市,从一个城市开始走,还剩下十九个城市,且最后一个城市的边相邻城市能回到原来的第一个城市。

2.搜索思路:如果这个点可以继续搜索,说明这条路可行,继续往下搜,如果不行,就退回将这个点取消标记。

#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
int a[25][5];//存地图
int book[30];//标记这个城市是否走过
int ans[30]; //存答案
int n = 1;
int m;

void dfs(int step,int start,int restart)//restart:这一次的终点,下一次的起点
{
    ans[step]=restart;
    book[restart]=1;
    for(int i=1; i<=3; i++)
    {
        int p=a[restart][i];
        if(step==19&&p==start)
        {
            cout<<n<<":"<<" "<<" ";
            n++;
            for(int j=0; j<20; j++)
                cout<<ans[j]<<" ";
            cout<<start<<endl;
        }
        if(book[p]==0)
            dfs(step+1,start,p);
    }
    book[restart]=0;
}

int main()
{
    for(int i=1; i<=20; i++)
        cin>>a[i][1]>>a[i][2]>>a[i][3];
    while(scanf("%d",&m)!=EOF&&m!=0)
    {
        memset(book,0,sizeof(book));
        book[m]=1;
        n=1;
        dfs(0,m,m);
    }
    return 0;
}

https://vjudge.net/contest/547627#problem/Mhttps://vjudge.net/contest/547627#problem/M

题意:#是传送门,*是墙,.是路,求是否在规定的时间内救出人

题解:

1.首先如果没有层数,就是二维的bfs题目,运用队列,走一步时间+1。然后分两种情况:

  1. 如果时间在未达到终点的时候时间已经超过规定时间,那么就已经可以结束了。
  2. 如果时间在达到终点的时候时间小于或等于规定时间,那么就可以救出人。

2.在1的基础上再考虑传送门,因为有两层,在第一层传送门会将用户送到第二层,在第二层会将用户送到第一层,所以当走到传送门的时候要给一个判断,下一个点应该在哪一层。

传送门的一些坑点:

  1. 传送过去的点不能是传送门,如果是下一个对应的点也是传送门,两个传送门来回传送,这是一个死循环。
  2. 传送过去是个墙用户会一头撞死。
  3. 传送过去是终点就可以直接结束。

3.如果无论如何都达到不了终点,说明永远找不到这个人,也是无解。


#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
int book[2][20][20];
char a[2][20][20];
const int N=1e6+10;
int n, m, time;
int head,tail;
int dx[]= {1,-1,0,0};
int dy[]= {0,0,1,-1};



struct node
{
    int x;
    int y;
    int z;
    int t;
} que[N];


int judge(int a)
{
    if(a==1)
        return 0;
    else
        return 1;
}

int bfs(int z,int x,int y)
{
    head=tail=0;
    que[tail].x=x;
    que[tail].y=y;
    que[tail].z=z;
    que[tail].t=0;
    book[z][x][y]=1;
    tail++;
    int flag=0;
    while(head<tail)
    {
        for(int i=0; i<4; i++)
        {
            int nx=que[head].x+dx[i];
            int ny=que[head].y+dy[i];
            int nz=que[head].z;
            if(nx<0||nx>=n||ny<0||ny>=m)
                continue;
            if(a[nz][nx][ny]=='.'&&book[nz][nx][ny]==0)
            {
                book[nz][nx][ny]=1;
                que[tail].x=nx;
                que[tail].y=ny;
                que[tail].z=nz;
                que[tail].t=que[head].t+1;
               // cout<<que[tail].z<<endl;
               // cout<<que[tail].t<<endl;
                if(que[tail].t>time)//如果达到这个点已经无法救出人,那就没必要继续了
                    return -1;
                tail++;
            }
            else if(a[nz][nx][ny]=='*'||book[nz][nx][ny]==1)
                continue;
            else if(a[nz][nx][ny]=='#')
            {
                a[nz][nx][ny]=1;
                int dz=judge(nz);
                if(a[dz][nx][ny]!='#'&&a[dz][nx][ny]!='*'&&book[dz][nx][ny]==0)
                {
                    if(a[dz][nx][ny]=='P'&&que[head].t+1<=time)//传送到终点可以直接退出
                        return 1;
                    book[dz][nx][ny]=1;
                    que[tail].x=nx;
                    que[tail].y=ny;
                    que[tail].z=dz;
                    que[tail].t=que[head].t+1;
                   // cout<<que[tail].z<<endl;
                   // cout<<que[tail].t<<endl;
                    if(que[tail].t>time)
                        return -1;
                    tail++;
                }

            }
            else if(a[nz][nx][ny]=='P'&&que[head].t+1<=time)//达到终点
            {
                // flag=1;
                return 1;
            }
        }
        //  if(flag==1)
        //     break;
        head++;
    }
    return -1;
}


int main()
{
    int c;
    cin >> c;
    while (c--)
    {
        memset(book,0,sizeof(book));
        memset(que,0,sizeof(que));
        cin >> n >> m >> time;
        for (int i = 0; i < 2; i++)
        {
            for (int j = 0; j < n; j++)
            {
                scanf("%s",a[i][j]);
                getchar();
            }
        }
        int flag=bfs(0,0,0);
        if(flag==1)
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
    }
    return 0;
}

 https://vjudge.net/contest/547627#problem/Ghttps://vjudge.net/contest/547627#problem/G

 题意:两个人走,找一个可以达到是两人一起用时最小的KFC

题解:找最短时间,bfs题目,只是有两个人,要用两次bfs,并且两个人是分开走的,不是一起走。算出一起走的步数,然后步数*11就是时间;

实现步数的方法:先让一个人走,存下这个人到所有KFC的步数,再让另一个人走,当达到同一个KFC并且这个人的步数不为0(说明这个人走过)就将步数相加,然后再寻找达到KFC步数最小的,然后输出

#include <string.h>
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
using namespace std;
const int N=210;
const int M=2e6+10;
char a[N][N];
int n,m;
int mx,my,yx,yy;

int book[N][N]= {0};
int step[N][N]= {0};

int time[M];
int temp[M];
struct node
{
    int x,y,step;
} que1[M],que[M];
int dx[]= {1,0,-1,0};
int dy[]= {0,1,0,-1};

int head,tail;
int head1,tail1;


void bfsy(int x,int y)
{
    head=tail=0;
    que[tail].x=x;
    que[tail].y=y;
    que[tail].step=0;
    book[x][y]=1;
    tail++;
    while(head<tail)
    {
        for(int i=0; i<4; i++)
        {
            int nx=que[head].x+dx[i];
            int ny=que[head].y+dy[i];
            if(nx<0||nx>=n||ny<0||ny>=m||book[nx][ny]==1||a[nx][ny]=='#')
                continue;
            book[nx][ny]=1;
            que[tail].x=nx;
            que[tail].y=ny;
            que[tail].step=que[head].step+1;
            step[nx][ny]=que[head].step+1;
            //cout<<endl<<endl;
            tail++;

        }
        head++;
    }
}


void bfsm(int x,int y)
{
    head1=tail1=0;
    que[tail1].x=x;
    que[tail1].y=y;
    que[tail1].step=0;
    book[x][y]=1;
    if(step[x][y]!=0&&que[tail1].step!=0)
        step[x][y]+=que[tail1].step;
    tail1++;
    while(head1<tail1)
    {
        for(int i=0; i<4; i++)
        {
            int nx=que[head1].x+dx[i];
            int ny=que[head1].y+dy[i];
            if(nx<0||nx>=n||ny<0||ny>=m||book[nx][ny]==1||a[nx][ny]=='#')
                continue;
            book[nx][ny]=1;
            que[tail1].x=nx;
            que[tail1].y=ny;
            que[tail1].step=que[head1].step+1;
            if(a[nx][ny]=='@'&&step[nx][ny]!=0&&que[tail1].step!=0)//到达同一个KFC并且第二个人走过
                step[nx][ny]+=que[tail1].step;
            //cout<<que[tail1].step<<" ";
            // cout<<endl<<endl;
            tail1++;

        }
        head1++;
    }
}

int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(book,0,sizeof(step));
        memset(book,0,sizeof(book));
        memset(book,0,sizeof(a));
        for(int i=0; i<n; i++)
        {
            scanf("%s",a[i]);
            getchar();

        }
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<m; j++)
            {
                if(a[i][j]=='Y')
                    yx=i,yy=j;
                if(a[i][j]=='M')
                    mx=i,my=j;
            }
        }
        bfsy(yx,yy);
        memset(book,0,sizeof(book));
        bfsm(mx,my);
        int min1=999999;
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<m; j++)
            {
                if(a[i][j]=='@'&&step[i][j]!=0)
                {
                    if(step[i][j]<min1)
                    {
                        min1=step[i][j];
                    }
                }
            }
        }
        cout<<min1*11<<endl;
    }
    return 0;
}

 https://codeforces.com/contest/1806/problem/A

题意:一个人在一个点,有两种变法:左右或者沿着对角线往上移,问能否通过这两种变法能否达到终点

题解:由于x有两种变法,y只有一种变法,所以以y为基准:分三种情况:

  1. 如果起始点的y比终点的y大,由于y只能由起始点往上移,不能往下移,所以绝对无法到达,输出-1;
  2. 如果起始点和终点的y一样,分三种情况:
  • 如果起始点和终点的x一样,起始点和终点重合,不需要移动,输出0
  • 如果起始点的x大于终点x,由于可以往左边移,所以答案就是终点x到起点x的距离
  1. 如果起始点的x小于终点x,不能往右边移,否则会造成y的改变,所以绝对无法到达,输出-1如果起始点的y小于终点的y,三种情况:
  • 首先先确定y上移的距离,y上移的距离也是x上移的距离,让起始点加上y上移的距离得到一个新的起点
  • 如果新起点的x等于终点的x,输出y移动的距离;
  • 如果新起点的x小于终点的x,由于无法右移,所以无法到达,输出-1;
  • 如果新起点的x大于终点的x,可以往左移,所以答案就是y变化的距离+x左移的距离
#include <stdio.h>
#include <iostream>
#include <math.h>
using namespace std;
int a,b,c,d;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin>>a>>b>>c>>d;
        if(b>d) cout<<"-1"<<endl;
        else if(b==d)
        {
            if(a<c)
                cout<<"-1"<<endl;
            else if(a==c) cout<<"0"<<endl;
            else if(a>c) cout<<abs(a-c)<<endl;
        }
        else if(b<d)
        {
            int m=abs(b-d);
            int k=a+m;
            if(k==c) cout<<m<<endl;
            else if(k>c) cout<<m+abs(k-c)<<endl;
            else if(k<c) cout<<"-1"<<endl;
        }
    }
    return 0;
}

https://codeforces.com/contest/1806/problem/B

题意:给你一串数字,给这段数字排序,形成一个

[a1+a2,a2+a3,…,an−1+an][a1+a2,a2+a3,…,an−1+an]这样的新数列,然后输出最小的非负整数

题解:利用插空法,讨论0的个数和0能产生的空位数是否能被0以外的数字填充完

1.当0的个数<=(总长度+1)/  2时,0产生的空位是可被填充完毕的,新数列不会出现0,所以最小非负整数就是0;

2.当0的个数大于(总长度+1)/  2时,0的空位无法被填充完,所以一定会产生0,最小非负整数就要往后考虑,这时候就分两种情况:

  • 如果这个原数字串里面没有出现1,无论怎么样排列,都无法凑出1,所以最小非负整数一定是1;或者在有数字1的同时出现了其他数字,可以将1和其他数字放在一起,凑成>1的其他数字,此时最小的非负整数还是1;
  • 剩下的就是没有其他的数字,只有1,那么就可以将1填充到0中,是最小非负整数为2;

#include <iostream>
 
using namespace std;
 
int main()
{
    int t=0;
    cin >> t;
    while (t--)
    {
        int p, q, s;
        p=q=s=0;
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            int x = 0;
            cin>>x;
            if(x==0)
                p++;
            else if(x==1)
                q++;
            else
                s++;
        }
        int l=(n+1)/2;
        if(p<=l) cout<<"0"<<endl;
        else if(p>l)
        {
            if(s!=0||q==0)
                cout<<"1"<<endl;
            else
                cout<<"2"<<endl;
        }
 
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值