20211013华为机试分享
第一题100分
小明家有很大的房子,有很多房间。先输入roomA,然后输入roomB,再输入门的个数N。
接着输入N行门,意味着可以从一个房间(第一个数字)到另一个房间(第二个数字)。
请问从roomA到roomB最短的要经过几个门
输入:
1
5
5
1 2
2 3
3 4
2 5
4 5
这道题很像leetcode的课程表,就是要注意一个房间可能可以到达多个房间,所以字典value是list
import sys
from collections import defaultdict
if __name__ == "__main__":
# 读取第一行的n
# 都是string
roomA = input().strip()
roomB = input().strip()
N = int(input().strip())
# 保存门
doors=defaultdict(list)
# 保存路径
visited=[]
# 保存答案
res=[]
path=[]
for i in range(N):
door=input().strip().split()
door1,door2=door[0],door[1]
doors[door1].append(door2)
doors[door2].append(door1)
def dfs(room1):
# 到达终点
if room1==roomB:
# 取消注释可以看路径
#path.append(visited.copy())
res.append(len(visited))
return
elif room1 in visited:
return
else:
# 刚刚进入room1
visited.append(room1)
to_visit=doors[room1]
for room in to_visit:
dfs(room)
visited.pop()
dfs(roomA)
# res元素最短长度
#print(res)
#print(path)
print(min(res)) 第二题200分
一个m*n的陆地板块,中间有湖,湖是不能走的。
先输入m n,再输入起点坐标,终点坐标。
然后输入湖的个数n。
下面n行输入湖的坐标。
需要输出从起点到终点的最短路径的数量和最短路径所经过的距离
输入:
5 5
0 1
5 5
1
2 1
这道题看起来简单,实际上要注意一下路径数量会非常多。需要用堆去优化结果,另外还需要在visited已经长于之前搜索过的路径的时候提前中止。
还有,可能不能到达所以需要输出0 0
import heapq
if __name__ == "__main__":
m,n=input().strip().split()
m,n=int(m),int(n)
line=input().strip().split()
Start=(int(line[0]),int(line[1]))
line=input().strip().split()
End=(int(line[0]),int(line[1]))
line=input().strip()
Lakes_num=int(line)
Lakes=set()
for i in range(Lakes_num):
line=input().strip().split()
Lakes.add( (int(line[0]),int(line[1])) )
visited=set()
visited.add(Start)
res=[]
#Paths=[]
direcs=[[0,1],[0,-1],[1,0],[-1,0]]
def dfs(pos):
if pos==End:
#Paths.append(visited.copy())
val=len(visited)
if not res:
heapq.heappush(res, val)
else:
cur_min=heapq.heappop(res)
if val<cur_min:
heapq.heappush(res, val)
elif val==cur_min:
heapq.heappush(res, val)
heapq.heappush(res, val)
else:
heapq.heappush(res, cur_min)
return
elif res and len(visited)>res[0]:
return
else:
x0,y0=pos[0],pos[1]
for dx,dy in direcs:
x,y=x0+dx,y0+dy
if 0<=x<m and 0<=y<n and (x,y) not in visited and (x,y) not in Lakes:
visited.add((x,y))
dfs((x,y))
visited.remove((x,y))
if m*n==0:
print("0 0")
exit()
elif m==1 or n==1 and Lakes_num!=0:
print("0 0")
exit()
else:
dfs(Start)
if not res:
print("0 0")
else:
MIN=res[0]
ans=0
while res:
tmp=heapq.heappop(res)
if tmp==MIN:
ans+=1
else:
break
print(ans,MIN-1)
#print(Paths) 第三题 300分
(我没做出来!)
搜到了leetcode原题:编码最短长度的字符串:
给定一个 非空 字符串,将其编码为具有最短长度的字符串。
编码规则是:k[encoded_string],其中在方括号 encoded_string 中的内容重复 k 次。
注:
k 为正整数
如果编码的过程不能使字符串缩短,则不要对其进行编码。如果有多种编码方式,返回 任意一种 即可
string encode(string s) {
vector<vector<string>> d(s.size(),vector<string>(s.size(),""));
return dfs(s,0,s.size()-1,d);
}
string dfs(const string s,int i,int j,vector<vector<string>>& d){
if(i > j) return "";
string& ans=d[i][j];
if(ans.size()) return ans;
int len = j-i+1;
ans=s.substr(i,len);
if(len < 5) return ans;
int p=(ans+ans).find(ans,1);
if(p < len){
ans=to_string(len/p)+"["+dfs(s,i,i+p-1,d)+"]";
}
for(int k=i;k<j;++k){
string c=dfs(s,i,k,d);
string e=dfs(s,k+1,j,d);
if(c.size()+e.size() < ans.size()){
ans=c+e;
}
}
return ans;
}#华为##笔经#