HRBU 2021年暑期训练阶段二Day2

目录

A - Lake Counting

题目链接:

题意:

B - Binary Search

题目链接:

题意:

做法:

C - Fire!

题目链接:

题意:

做法:

D - Find a way

题目链接:

题意:

做法:

E - Power Calculus

题目链接:

题意:

做法:

F - Find The Multiple

题目链接:

题意:

做法:

G - 棋盘问题

题目链接:

题意:

做法:


A - Lake Counting

题目链接:

https://vjudge.net/contest/451796#problem/A

题意:

与上一天的油田类似,详情可以参照这个博客里的G题

点击这里

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<string.h>
#include<cstdlib>
#include<fstream>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
const int maxn=110;
int n,m,cnt=0,flag;
int dir[8][2]= {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};
char mp[maxn][maxn];

int dfs(int x,int y)
{
    if(mp[x][y]=='.')
        return flag;
    mp[x][y]='.';
    flag=1;
    for(int i=0;i<8;i++)
    {
        int xx=x+dir[i][0];
        int yy=y+dir[i][1];
        if(xx>=1&&xx<=n&&yy>=1&&yy<=m)
            dfs(xx,yy);
    }
    return flag;
}

int main()
{
    while(cin>>n>>m)
    {
        cnt=0;
        if(n==0&&m==0)
            break;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
                cin>>mp[i][j];
        }
        //cout<<1<<endl;
        for(int i=1;i<=n;i++)
        {
            //cout<<"i:"<<i<<endl;
            for(int j=1;j<=m;j++)
            {
                flag=0;
                if(dfs(i,j))
                    cnt++;
            }
            //cout<<"i+1:"<<i+1<<endl;
        }
        //cout<<2<<endl;
        cout<<cnt<<endl;
    }
    return 0;
}

B - Binary Search

题目链接:

https://vjudge.net/contest/451796#problem/B

题意:

给定两个数组,要求计算出两个数组中的相同的元素的个数

做法:

n的范围决定了我们不能使用正常的查找方法(冒泡,选择之类的)所以我们采用万能的二分查找(自己觉得的,别刚,刚就是你赢)自己写的二分答案,比较数组里的数据是否比现在的值大,是的话就把右区间左移,否则做左区间右移,也可以调用Binary Search函数

函数介绍博客:http://m.biancheng.net/view/7537.html

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<string.h>
#include<cstdlib>
#include<fstream>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int n,q,cnt=0,T;
int dir[8][2]= {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};
int S[maxn];

bool slove(int x)
{
    int l=0,r=n,mid;
    while(l<r)
    {
        mid=(l+r)/2;
        if(x<S[mid])
            r=mid;
        else if(x>S[mid])
            l=mid+1;
        else
            return true;
    }
    return false;
}

int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>S[i];
    }
    cin>>q;
    for(int i=0;i<q;i++)
    {
        cin>>T;
        if(slove(T))
            cnt++;
    }
    cout<<cnt<<endl;
    return 0;
}

C - Fire!

题目链接:

https://vjudge.net/contest/451796#problem/C

题意:

一个迷宫之中存在着一个人和一团火,要求人在被火烧死之前逃出这个迷宫,逃出迷宫的条件就是移动到迷宫的边界没有墙壁的地方,人和火都不能穿过墙壁,以及火呈蔓延式扩散,每一秒扩散四个方向(上下左右)

做法:

当这个人能跑出去时,我们需要满足两个条件:1、这个人不会被火堵住去路。2、这个人能找到出口,也就是没有墙壁的边界。因此我们需要对火和人都进行一次搜索,对于火的搜索就是这个火到达某一个地方需要多少时间;而对于人的搜索则是这个人是否在火到达之前到达了应该到达的位置或者这个人的下一步路有没有被火给堵上。两边BFS即可

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<string.h>
#include<cstdlib>
#include<fstream>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const ll maxn=1e3+10;
int n,m,sx,sy;
int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
char mp[maxn][maxn];
int times[maxn][maxn],step[maxn][maxn];
bool vis[maxn][maxn];
struct Node
{
    int x,y,step;
};
queue<Node> Q;

bool judge(int x,int y)
{
    if(x<1||x>n||y<1||y>m)
        return false;
    if(vis[x][y])
        return false;
    return mp[x][y]=='.';
}

void Fire_bfs()
{
    while(!Q.empty())
    {
        Node now=Q.front();
        Q.pop();
        for(int i=0;i<4;i++)
        {
            int xx=now.x+dir[i][0];
            int yy=now.y+dir[i][1];
            if(judge(xx,yy))
            {
                vis[xx][yy]=true;
                times[xx][yy]=times[now.x][now.y]+1;
                Q.push((Node){xx,yy,times[xx][yy]});
            }
        }
    }
}

void clear_Q()
{
    while(!Q.empty())
        Q.pop();
}

int J_bfs(int x,int y)
{
    step[x][y]=0;
    Q.push((Node){x,y,0});
    vis[x][y]=true;
    while(!Q.empty())
    {
        Node now=Q.front();
        Q.pop();
        if(now.x==1||now.x==n||now.y==1||now.y==m)
            return step[now.x][now.y]+1;
        for(int i=0;i<4;i++)
        {
            int xx=now.x+dir[i][0];
            int yy=now.y+dir[i][1];
            if(judge(xx,yy)&&step[now.x][now.y]+1<times[xx][yy])
            {
                step[xx][yy]=step[now.x][now.y]+1;
                vis[xx][yy]=true;
                Q.push((Node){xx,yy,step[xx][yy]});
            }
        }
    }
    return -1;
}

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n>>m;
        memset(vis,false,sizeof(vis));
        memset(times,INF,sizeof(times));
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                cin>>mp[i][j];
                if(mp[i][j]=='J')
                    sx=i,sy=j;
                if(mp[i][j]=='F')
                {
                    vis[i][j]=true;
                    times[i][j]=0;
                    Q.push((Node){i,j,0});
                }
            }
        }
        Fire_bfs();
        clear_Q();
        memset(vis,false,sizeof(vis));
        int ans=J_bfs(sx,sy);
        if(ans==-1)
            cout<<"IMPOSSIBLE"<<endl;
        else
            cout<<ans<<endl;
    }
    return 0;
}

D - Find a way

题目链接:

https://vjudge.net/contest/451796#problem/D

题意:

两个人从不同的出发点出发,要到达固定的同一个位置,需要求出到达这个位置的两个人需要的最短时间是多少?每移动一个单元格需要11分钟

做法:

当两个人都要去往同一个目的地时,分别对于两个人进行搜索并且记录下一个时间值,之后再去遍历时间数组找到对于的位置,取出最小值,这不就满足了题目给予的条件了吗?最后输出时得×11以及不要忘记了一开始的起始步数是0,(最后的答案+2)×11才是我们想要的答案

#include <iostream>
#include <cstring>
#include<vector>
#include<string>
#include <cmath>
#include <map>
#include <queue>
#include <algorithm>
#include<cstdio>
using namespace std;
#define maxn 210
char tmp[maxn][maxn];
int yi,yj,mi,mj,n,m,time[maxn][maxn],ans=1e9+7;
bool vis[maxn][maxn];
int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
struct Node
{
    int x,y,step;
    Node(int x, int y,int step):x(x), y(y), step(step){}
};
void bfs(int pi,int pj)
{
    memset(vis,false,sizeof(vis));
    queue<Node> Q;
    vis[pi][pj]=true;
    Q.push(Node(pi,pj,0));
    while(!Q.empty())
    {
        Node now=Q.front();
        Q.pop();
        for(int i=0;i<4;i++)
        {
            int xx=now.x+dir[i][0];
            int yy=now.y+dir[i][1];
            if(xx>=0&&xx<n&&yy>=0&&yy<m&&!vis[xx][yy]&&tmp[xx][yy]!='#')
            {
                vis[xx][yy]=true;
                time[xx][yy]+=now.step;
                Q.push(Node(xx,yy,now.step+1));
            }
        }
    }
}
int main()
{
   while(scanf("%d%d",&n,&m)!=EOF)
   {
       ans=1e9+7;
       memset(time,0,sizeof(time));
       for(int i=0;i<n;i++)
       {
           cin>>tmp[i];
           for(int j=0;j<m;j++)
           {
               if(tmp[i][j]=='Y')
               {
                   yi=i;
                   yj=j;
               }
               if(tmp[i][j]=='M')
               {
                   mi=i;
                   mj=j;
               }
           }
       }
       bfs(yi,yj);
       bfs(mi,mj);
       for(int i=0;i<n;i++)
       {
           for(int j=0;j<m;j++)
           {
               if(time[i][j]&&tmp[i][j]=='@')
                ans=min(ans,time[i][j]);
           }
       }
       cout<<(ans+2)*11<<endl;
   }
   return 0;
}

E - Power Calculus

题目链接:

https://vjudge.net/contest/451796#problem/E

题意:

对于给定的整数x进行x^n计算,要求求出最少的运算次数(只能运用乘法和除法),题目中解释了样例,我就不过多赘述了(怕自己说不明白.jpg

做法:

是熟悉的IDA*呀,迭代加深搜索,我们对于每次的乘法除法都转变为对于幂位置的加减运算,以及每一的回溯都对于幂指数进行判断,满足条件则继续下一次搜索,否则则返回

推荐博客:点这里

#include <iostream>
#include <cstring>
#include<vector>
#include<string>
#include <cmath>
#include <map>
#include <queue>
#include <algorithm>
#include<cstdio>
using namespace std;
#define maxn 210
typedef long long ll;
int val[1010],pos,n;

bool dfs(int x,int depth)
{
    if(x>depth)
        return false;
    if(val[pos]<<(depth-x)<n)
        return false;
    if(val[pos]==n)
        return true;
    pos++;
    for(int i=0;i<pos;i++)
    {
        val[pos]=val[pos-1]+val[i];
        if(dfs(x+1,depth))
            return true;
        val[pos]=abs(val[pos-1]-val[i]);
        if(dfs(x+1,depth))
            return true;
    }
    pos--;
    return false;
}

int main()
{
    while(cin>>n&&n)
    {
        int de;
        for(de=0;;de++)
        {
            val[pos=0]=1;
            if(dfs(0,de))
                break;
        }
        cout<<de<<endl;
    }
    return 0;
}

F - Find The Multiple

题目链接:

https://vjudge.net/contest/451796#problem/F

题意:

输入一个在1到200之间的整数,需要我们求出一个只包含0,1的数字能够整除这个n

做法:

构思一下,一个数字只包含0,1,如果我们要去表示这个数字的话,不就可以使用10这个数字了吗

10*x这样是只有一个1和x个0,10*x+1则是两个1以及x-1个0,满足了我们数字中只包含0,1的条件,接着我们只要去把这些数字一个个进行判断就好了,注意的是这题有特殊判断,所以输出的答案和样例不一定完全相同

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<string.h>
#include<cstdlib>
#include<fstream>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
const ll maxn=1e7+10;
int n,q,cnt=0,flag;

void slove()
{
    queue<ll> Q;
    while(!Q.empty())
        Q.pop();
    Q.push(1);
    while(1)
    {
        ll now=Q.front();
        if(now%n==0)
        {
            cout<<now<<endl;
            return;
        }
        Q.pop();
        Q.push(now*10);
        Q.push(now*10+1);
    }
}

int main()
{
    while(cin>>n&&n)
    {
        slove();
    }
    return 0;
}

G - 棋盘问题

题目链接:

https://vjudge.net/contest/451796#problem/G

题意:

中文!自己康

做法:

标准的深搜,快快乐乐的搜索就完了

#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<string.h>
using namespace std;
const int maxn=10;
int n,m,sum=0;
struct Node
{
    char ch[maxn][maxn];
    int x;//上一个棋子所在行数
};
Node mp;
void dfs(Node mp,int b)
{
    if(b==0)
    {
        sum++;
        return;
    }
    for(int i=mp.x+1; i<=n-b; i++)
    {
        for(int j=0; j<n; j++)
        {
            if(mp.ch[i][j]=='#')
            {
                Node tmp;
                tmp=mp;
                tmp.x=i;
                for(int k=i+1; k<n; k++)
                    tmp.ch[k][j]='.';
                dfs(tmp,b-1);
            }
        }
    }
}
int main()
{
    while(cin>>n>>m&&n!=-1&&m!=-1)
    {
        for(int i=0; i<n; i++)
            cin>>mp.ch[i];
        mp.x=-1;
        sum=0;
        dfs(mp,m);
        cout<<sum<<endl;
    }
    return 0;
}
上一篇:0904csp七连day2比赛总结


下一篇:Protocol 模拟UI中一个按钮点击改变lable中的值