“战疫杯”大学生程序设计在线邀请赛(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的复杂度下进行二分查找