Acwing 的练习题

13 篇文章 0 订阅

目录

1.1064问题 AE: 互不侵犯

2.1097池塘计数问题 L: 数水塘

3 1098 城堡问题

4 1106 山峰和山谷

5 1076 迷宫问题

6 1100 抓住那头牛


1.1064问题 AE: 互不侵犯

时间限制: 1.000 Sec  内存限制: 128 MB
提交 状态

题目描述

在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。

输入

只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)

输出

方案数。

样例输入 Copy

3 2

样例输出 Copy

16
#include<bits/stdc++.h>
using namespace std;
const int N=12,M=1<<10,K=110;
vector<int>head[M];
vector<int>state;
long long f[N][K][M];
int n,m;
int cnt[M];
bool check(int state)
{
    for(int i=0;i<n;i++){
        if((state>>i&1)&&(state>>i+1&1)){
            return false;
        }
    }
    return true;
}
int count(int state)
{
    int res=0;
    for(int i=0;i<n;i++)res+=state>>i&1;
    return res;
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<1<<n;i++){
        if(check(i)){
            state.push_back(i);
            cnt[i]=count(i);
        }
    }
    for(int i=0;i<state.size();i++){
        for(int j=0;j<state.size();j++){
            int a=state[i],b=state[j];
            if((a&b)==0&&check(a|b)){
                head[i].push_back(j);
            }
        }
    }
    f[0][0][0]=1;
    for(int i=1;i<=n+1;i++){
        for(int j=0;j<=m;j++){
            for(int k=0;k<state.size();k++){
                for(auto b:head[k]){
                    int c=cnt[state[k]];
                    if(j>=c){
                        f[i][j][k]+=f[i-1][j-c][b];
                    }
                }
            }
        }
    }
    cout<<f[n+1][m][0];
    return 0;
}

每天写点题和题解 预防衰老

2.1097池塘计数问题 L: 数水塘

时间限制: 1.000 Sec  内存限制: 128 MB
提交 状态

题目描述

给定一个 N x M (1 <= N <= 100; 1 <= M <= 100) 的区域.每个区域用'W'表示有水,用.表示陆地。 如果一个区域有水且它相邻的区域也有水则同属一个水塘。一个区域最多有八个相邻的区域。根据,给定的地图现在要统计有多少个水塘。

输入

第一行:两个用空格隔开的整数N和M 
第2..N+1行:每行M个字符,每个字符为 'W' 或 '.'。

输出

一行:一个整数表示水塘的个数 

样例输入 Copy

10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.

样例输出 Copy

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
char g[N][N];
bool st[N][N];
int n,m;
typedef pair<int,int>PII;
void dfs(int x,int y)
{
    queue<PII>q;
    q.push({x,y});
    while(!q.empty()){
        int x=q.front().first,y=q.front().second;
        q.pop();
        for(int i=x-1;i<=x+1;i++){
            for(int j=y-1;j<=y+1;j++){
                if(i<0||i>=n||j<0||j>=m)continue;
                if(g[i][j]=='.'||st[i][j])continue;
                if(i==x&&j==y)continue;
                q.push({i,j});
                st[i][j]=true;
            }
        }
    }
}
int main()
{
    cin>>n>>m;
    int ans=0;
    for(int i=0;i<n;i++)cin>>g[i];
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(!st[i][j]&&g[i][j]=='W'){
                dfs(i,j);
                ans++;
            }
        }
    }
    cout<<ans;
    return 0;
}

3 1098 城堡问题

    1   2   3   4   5   6   7  
   #############################
 1 #   |   #   |   #   |   |   #
   #####---#####---#---#####---#
 2 #   #   |   #   #   #   #   #
   #---#####---#####---#####---#
 3 #   |   |   #   #   #   #   #
   #---#########---#####---#---#
 4 #   #   |   |   |   |   #   #
   #############################
           (图 1)

   #  = Wall   
   |  = No wall
   -  = No wall

   方向:上北下南左西右东。

图1是一个城堡的地形图。

请你编写一个程序,计算城堡一共有多少房间,最大的房间有多大。

城堡被分割成 m∗nm∗n个方格区域,每个方格区域可以有0~4面墙。

注意:墙体厚度忽略不计。

输入格式

第一行包含两个整数 mm 和 nn,分别表示城堡南北方向的长度和东西方向的长度。

接下来 mm 行,每行包含 nn 个整数,每个整数都表示平面图对应位置的方块的墙的特征。

每个方块中墙的特征由数字 PP 来描述,我们用1表示西墙,2表示北墙,4表示东墙,8表示南墙,PP 为该方块包含墙的数字之和。

例如,如果一个方块的 PP 为3,则 3 = 1 + 2,该方块包含西墙和北墙。

城堡的内墙被计算两次,方块(1,1)的南墙同时也是方块(2,1)的北墙。

输入的数据保证城堡至少有两个房间。

输出格式

共两行,第一行输出房间总数,第二行输出最大房间的面积(方块数)。

数据范围

1≤m,n≤501≤m,n≤50,
0≤P≤150≤P≤15

输入样例:

4 7 
11 6 11 6 3 10 6 
7 9 6 13 5 15 5 
1 10 12 7 13 7 5 
13 11 10 8 10 12 13 

输出样例:

5
9

 

#include<bits/stdc++.h>
using namespace std;
const int N=55;
int g[N][N];
bool st[N][N];
int n,m;
int dx[4]={0,-1,0,1},dy[4]={-1,0,1,0};
typedef pair<int,int>PII;
int bfs(int x,int y)
{
    int area=0;
    queue<PII>q;
    q.push({x,y});
    st[x][y]=true;
    while(!q.empty())
    {
        auto t=q.front();
        q.pop();
        area++;
        for(int i=0;i<4;i++){
            int a=t.first+dx[i],b=t.second+dy[i];
            if(a<0||a>=n||b<0||b>=m)continue;
            if(st[a][b])continue;
            if(g[t.first][t.second]>>i&1)continue;
            q.push({a,b});
            st[a][b]=true;
        }
        
    }
    return area;
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            cin>>g[i][j];
        }
    }
    int ans=0,area=0;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(!st[i][j]){
                area=max(area,bfs(i,j));
                ans++;
            }
        }
    }
    cout<<ans<<endl<<area;
    return 0;
}

4 1106 山峰和山谷

FGD小朋友特别喜欢爬山,在爬山的时候他就在研究山峰和山谷。

为了能够对旅程有一个安排,他想知道山峰和山谷的数量。

给定一个地图,为FGD想要旅行的区域,地图被分为 n×nn×n 的网格,每个格子 (i,j)(i,j) 的高度 w(i,j)w(i,j) 是给定的。

若两个格子有公共顶点,那么它们就是相邻的格子,如与 (i,j)(i,j) 相邻的格子有(i−1,j−1),(i−1,j),(i−1,j+1),(i,j−1),(i,j+1),(i+1,j−1),(i+1,j),(i+1,j+1)(i−1,j−1),(i−1,j),(i−1,j+1),(i,j−1),(i,j+1),(i+1,j−1),(i+1,j),(i+1,j+1)。

我们定义一个格子的集合 SS 为山峰(山谷)当且仅当:

  1. SS 的所有格子都有相同的高度。
  2. SS 的所有格子都连通。
  3. 对于 ss 属于 SS,与 ss 相邻的 s′s′ 不属于 SS,都有 ws>ws′ws>ws′(山峰),或者 ws<ws′ws<ws′(山谷)。
  4. 如果周围不存在相邻区域,则同时将其视为山峰和山谷。

你的任务是,对于给定的地图,求出山峰和山谷的数量,如果所有格子都有相同的高度,那么整个地图即是山峰,又是山谷。

输入格式

第一行包含一个正整数 nn,表示地图的大小。

接下来一个 n×nn×n 的矩阵,表示地图上每个格子的高度 ww。

输出格式

共一行,包含两个整数,表示山峰和山谷的数量。

数据范围

1≤n≤10001≤n≤1000,
0≤w≤1090≤w≤109

输入样例1:

5
8 8 8 7 7
7 7 8 8 7
7 7 7 7 7
7 8 8 7 8
7 8 8 8 8

输出样例1:

2 1

输入样例2:

5
5 7 8 3 1
5 5 7 6 6
6 6 6 2 8
5 7 2 5 8
7 1 0 1 7

输出样例2:

3 3
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int g[N][N];
bool st[N][N];
int n;
typedef pair<int,int>PII;
void bfs(int x,int y,bool& h,bool& l)
{
    queue<PII>q;
    q.push({x,y});
    st[x][y]=true;
    while(!q.empty()){
        auto t=q.front();
        q.pop();
        int x=t.first,y=t.second;
        for(int i=x-1;i<=x+1;i++){
            for(int j=y-1;j<=y+1;j++){
                if(i<0||i>=n||j<0||j>=n)continue;
                if(g[i][j]!=g[x][y]){
                    if(g[i][j]>g[x][y])h=true;
                    else l=true;
                }else if(!st[i][j]){
                    st[i][j]=true;
                    q.push({i,j});
                }
            }
        }
    }
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            cin>>g[i][j];
        }
    }
    int peak=0,valley=0;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(!st[i][j]){
                bool h=false,l=false;
                bfs(i,j,h,l);
                if(!h)valley++;
                if(!l)peak++;
            }
        }
    }
    cout<<valley<<" "<<peak;
    return 0;
}

5 1076 迷宫问题

给定一个 n×nn×n 的二维数组,如下所示:

int maze[5][5] = {

0, 1, 0, 0, 0,

0, 1, 0, 1, 0,

0, 0, 0, 0, 0,

0, 1, 1, 1, 0,

0, 0, 0, 1, 0,

};

它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。

数据保证至少存在一条从左上角走到右下角的路径。

输入格式

第一行包含整数 n。

接下来 nn 行,每行包含 nn 个整数 0 或 1,表示迷宫。

输出格式

输出从左上角到右下角的最短路线,如果答案不唯一,输出任意一条路径均可。

按顺序,每行输出一个路径中经过的单元格的坐标,左上角坐标为 (0,0)(0,0),右下角坐标为 (n−1,n−1)(n−1,n−1)。

数据范围

0≤n≤10000≤n≤1000

输入样例:

5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0

输出样例:

0 0
1 0
2 0
2 1
2 2
2 3
2 4
3 4
4 4

 

#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
const int N=1010;
int n;
typedef pair<int,int>PII;
int g[N][N];
PII pre[N][N];
void dfs(int x,int y)
{
    queue<PII>q;
    int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
    q.push({x,y});
    memset(pre,-1,sizeof pre);
    pre[x][y]={0,0};
    while(!q.empty())
    {
        auto t=q.front();
        q.pop();
        for(int i=0;i<4;i++){
            int a=t.x+dx[i],b=t.y+dy[i];
            if(a<0||a>=n||b<0||b>=n)continue;
            if(g[a][b])continue;
            if(pre[a][b].x!=-1)continue;
            q.push({a,b});
            pre[a][b]=t;
        }
    }
}

int main()
{
    cin>>n;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            cin>>g[i][j];
        }
    }
    dfs(n-1,n-1);
    PII end(0,0);
    while(1){
        cout<<end.x<<" "<<end.y<<endl;
        if(end.x==n-1&&end.y==n-1)break;
        end=pre[end.x][end.y];
    }
    return 0;
}

6 1100 抓住那头牛

农夫知道一头牛的位置,想要抓住它。

农夫和牛都位于数轴上,农夫起始位于点 NN,牛位于点 KK。

农夫有两种移动方式:

  1. 从 XX 移动到 X−1X−1 或 X+1X+1,每次移动花费一分钟
  2. 从 XX 移动到 2∗X2∗X,每次移动花费一分钟

假设牛没有意识到农夫的行动,站在原地不动。

农夫最少要花多少时间才能抓住牛?

输入格式

共一行,包含两个整数N和K。

输出格式

输出一个整数,表示抓到牛所花费的最少时间。

数据范围

0≤N,K≤1050≤N,K≤105

输入样例:

5 17

输出样例:

4
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int f[N];
bool st[N];
int n,k;
int bfs()
{
    queue<int>q;
    q.push(n);
    memset(f,-1,sizeof f);
    f[n]=0;
    while(!q.empty())
    {
        int t=q.front();
        q.pop();
        if(t==k)return f[k];
        if(t+1<N&&f[t+1]==-1){
            f[t+1]=f[t]+1;
            q.push(t+1);
        }
        if(t-1>=0&&f[t-1]==-1){
            f[t-1]=f[t]+1;
            q.push(t-1);
        }
        if(t*2<N&&f[t*2]==-1){
            f[t*2]=f[t]+1;
            q.push(t*2);
        }
    }
}
int main()
{
    cin>>n>>k;
    cout<<bfs();
    return 0;
}

 好了 今天是1.13 浅浅刷这几道题吧

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值