郑州大学“战疫杯”大学生程序设计在线邀请赛(3)题解

“战疫杯”大学生程序设计在线邀请赛(3)题解

1. 疫情防控网络化

dfs判断连通性的问题,5分钟秒杀

具体做法

n,m = map(int,input().split())
nums = []
for i in range(n):
    nums.append(input())

f = [[False] * 110 for i in range(110)]

def dfs(x,y):
    if f[x][y]:
        return
    f[x][y] = True
    dx = [1,0,-1,0]
    dy = [0,1,0,-1]
    for i in range(4):
        nx = x + dx[i]
        ny = y + dy[i]
        if 0 <= nx < n and 0 <= ny < m and nums[nx][ny] == '#':
            dfs(nx,ny)

cnt = 0
for i in range(n):
    for j in range(m):
        if nums[i][j] == '#' and f[i][j] == False:
            dfs(i,j)
            cnt += 1
print(cnt)
2. 子区域计数

我不知道为什么,我tle了四次,把用python写的tle的代码转换成c++,ac了???出题人难道还卡语言?

原本这题都看不懂题目,还是做完一三题后当时才十几分钟后做的,结果卡到九点才ac,心里很气
题目意思就是求有多少个子矩阵,能满足四条边的边框上没有#的符号

希望下次出题,在样例下方加一个样例说明,要不然真是考阅读理解了

放一份python的tle的代码

n,m = map(int,input().split())
nums = []
for i in range(n):
    nums.append(input())

f = [[False] * 110 for i in range(110)]
cnt = 0
def check(x1,y1,x2,y2):
    for i in range(x1,x2+1):
        if nums[i][y1] == '#' or nums[i][y2] == '#':
            return False
    for i in range(y1,y2+1):
        if nums[x1][i] == '#' or nums[x2][i] == '#':
            return False
    return True

res = []
for i in range(n):
    for j in range(m):
        if nums[i][j] == '#':
            dx = [1,0,-1,0]
            dy = [0,1,0,-1]
            for k in range(4):
                nx = i + dx[k]
                ny = j + dy[k]
                if 0 <= nx < n and 0 <= ny < m and nums[nx][ny] == '*':
                    f[nx][ny] = True
cnt = 0
for i in range(n):
    for j in range(m):
        if f[i][j] or  nums[i][j] == '#':
            continue
        for k in range(i + 1,n):
            for l in range(j + 1,m):
                if nums[i][j] == '#' or f[k][l]:
                    continue
                if  check(i,j,k,l):
                    cnt += 1

print(cnt)

放一份C++的ac代码,就根据上面的代码翻译的hh

#include<bits/stdc++.h>
using namespace std;
int n,m;
bool f[110][110];
string a[110];
bool check(int x1,int y1,int x2,int y2){
    for(int i = x1;i <= x2;i++){
        if(a[i][y1] == '#' or a[i][y2] == '#'){
            return false;
        }
    }
    for(int j = y1;j <= y2;j++){
        if(a[x1][j] == '#' or a[x2][j] =='#'){
            return false;
        }
    }
    return true;
}
int main()
{
    cin >> n >> m;
    for(int i = 0;i < n ; i++){
        cin >> a[i];
        // scanf("%s",&a[i]);
    }
    for(int i = 0;i < n ;i ++){
        for(int j = 0;j < m;j ++){
           if(a[i][j] == '#'){
               int dx[4] = {1,0,-1,0};
               int dy[4] = {0,1,0,-1};
               for(int k = 0 ; k< 4;k++){
                   int nx = i + dx[k];
                   int ny = j + dy[k];
                   if(0 <= nx && nx < n && 0 <= ny && ny < m && a[nx][ny] == '#'){
                       f[nx][ny] = true;
                   }
               }
           }
        }
        // printf("\n");
    }
    long long cnt = 0;
    for(int i = 0;i < n;i ++){
        for (int j = 0; j < m; j ++ ){
            if( f[i][j] || a[i][j] == '#' ){
                continue;
            }
            for (int k = i+1;k<n;k++){
                for (int l = j+1;l<m;l++){
                    if (f[k][l] || a[i][j] == '#'){
                        continue;
                    }
                    if(check(i,j,k,l)){
                        cnt ++;
                    }
                }
            }
        }
    }
    cout << cnt;
}
3. 怀旧的思考挑战

简单模拟题

由于数据范围极小,可以直接四层循环暴力,看看哪四名选手的得分和等于n

n = int(input())
nums = [8,7,6,5,4,3,2,1]
res = 0
for i in range(8):
    for j in range(i+1,8):
        for k in range(j+1,8):
            for l in range(k+1,8):
                if nums[i] + nums[j] + nums[k] + nums[l] == n:
                    res += 1
if res != 0:
    print(res)
else:
    print("NO")

如果数据范围大的情况下,可以通过set优化掉最后一层循环

其次的优化解法,也可以通过logn的复杂度下进行二分查找

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力学习前端+Go的小菜鸡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值