洛谷搜索训练python代码

416 阅读11分钟

1.求细胞数量

www.luogu.com.cn/problem/P14…

这道题主要是搜索0与其他数字之间的间隔,可以写一个深搜,如果搜到0就返回,如果是1-9就继续搜索,读入需要使用二维数组,将每个点都遍历,只要没有标记过并且不是0的点就进行搜索,之后输出总值即可

x1 =[1,-1,0,0]
y1 =[0,0,1,-1]
n,m = map(int,input().split())
visit = [[0 for i in range(m+1)]for row in range(n+1)]
flag = [[0 for i in range(m+1)]for row in range(n+1)]
for i in range(n):  #进行输入
    temp = input()
    for j in range(m):
        visit[i][j] =temp[j]
​
def dfs(x, y):  # 使用dfs进行
    global flag
    if(x<0 or x>=n or y<0 or y>=m):
        return
    if (visit[x][y] == '0' or flag[x][y]):
        return
    flag[x][y] = 1
    for i in range(4):
        dfs(x+x1[i],y+y1[i]) #进行遍历sumvalue=0  #
for i in range(n):  #进行输入
    for j in range(m):
        if(visit[i][j]!='0' and (not flag[i][j])):     #如果不是0并且没有被标记
            dfs(i,j) #进行遍历
            sumvalue+=1
​
print(sumvalue)
​

2.组合的输出

www.luogu.com.cn/problem/P11…

对于这一题,主要是从1开始搜索,首先在数组中加入一个0可以访问-1,然后从小到大依次加入列表,判断是否达到了r长度,输出时使用%3d进行输出

code:

n,r = map(int,input().split())  #
def dfs(list1):
    if(len(list1)==r+1):
        for i in range(1,r+1):
            print("%3d"%(list1[i]),end='')
        print()
        return
    for i in range(list1[-1]+1,n+1):
        list1.append(i)
        dfs(list1)
        list1.pop()
a=[0]
dfs(a)

3.好奇怪的游戏

www.luogu.com.cn/problem/P17…

参考leetcode:leetcode-cn.com/problems/fl…

这样的搜索需要使用两种,这种的主要用广搜来做,因为是要求最小的步数,一层一层的进行,首先将初始条件进行put(),然后遍历所有方案之后进行put操作,依次执行后,找到第一个到达的就是最短路程.bfs与dfs的差别就是一个是在同层遍历,一个是在深层次遍历:

from queue import Queue
​
for i in range(2):
    endx,endy =map(int,input().split())
    que = Queue() #也就是使用Queue数据结构进行
    visit = [[0 for i in range(200)]for row in range(200)] #得到了visit的矩阵
    dx=[1,1,2,2,2,2,-1,-1,-2,-2,-2,-2]
    dy=[-2,2,-2,-1,1,2,-2,2,-1,1,-2,2]
    def bfs():
        que.put((1,1,0))
        while not que.empty():
            tempx,tempy,step = que.get()
            for i in range(12):
                x,y= tempx+dx[i],tempy+dy[i]
                if(x<0 or y<0 or x>=100 or y>=100 or visit[x][y]):
                    continue
                visit[x][y] = 1
                if((y==endy) and (x==endx)):
                    return step+1
                que.put((x,y,step+1)) #得到下一步的位置进入队列
​
​
    step = bfs()
    print(step)
    while not que.empty():  #消除队列中元素
        que.get()

4.血色先锋队

www.luogu.com.cn/problem/P13…

这一题主要是由多个传染源的话,只需要在一开始就把他们全部压入队列就行,之后再压出来进行bfs,

Code

from queue import Queue
​
dx =[1,-1,0,0]
dy =[0,0,1,-1]
n,m,a,b = map(int,input().split())
map1 = [[0 for i in range(m+1000)]for row in range(n+1000)]
queue = Queue(maxsize = 100000)  #Queue用来进行bfs.
def bfs():
    global map1 #也就是使用map
    while not queue.empty():
        tempx,tempy,step = queue.get()#得到每个点的信息
        for i in range(4):
            x,y = tempx+dx[i],tempy+dy[i]
            if(x>n+1 or x<0 or y<0 or y>m+1 or map1[x][y]): #如果这个东西很大了就必须扔掉
                continue
            map1[x][y] = step+1  #将这个step纪录下来
            queue.put((x,y,step+1))  #将x,y放入队列,并且放入step
​
for i in range(a):  #
    x,y = map(int,input().split())
    queue.put((x,y,0)) #也就是从0开始感染的话
    map1[x][y] = 10000
​
​
bfs()
for i in range(b):
    x,y = map(int,input().split())  #
    if(map1[x][y]==10000):
        print(0) #map1到底有多少
    else:
        print(map1[x][y])

5.数的划分

这个题主要是用搜索,构建一个函数纪录当前的遍历的数位置和使用的数的个数,当使用的数的个数等于k时,就判断与原来的数相等,相等就使方案加1,代码较简单

6.迷宫

www.luogu.com.cn/problem/P11…

这道题不同于其他的题目在于连通块的判断,首先我是用了一个递归进行赋值,但是出错的地方就在于不同方向的节点不相等,导致了WA,

关于深度优先搜索:

深度优先搜索写代码有两种,一种将判断条件写在最上层:

def dfs(value):
    if(seen[value]):    #如果已经访问过了 返回
        return
    seen[value]=True
    answer.append(value)
    for i in list1[value]:  #在列表中
        dfs(i)

如果只有一个起点开始的,可以将判断条件放在里面,但是使用上面那种更加通用

def dfs(value):            #
    seen[value]=True
    answer.append(value)
    for i in list1[value]:  #在列表中
        if(not seen[i]):    #如果已经访问过了 返回
            dfs(i)

关于广度优先搜索:

广度优先搜索都是用队列来写:

C语言的写完是这样的

void bfs(int x){   //bfs——广度优先遍历(x依然是第几号顶点,不过既然不递归其实传这个参数也没啥用)
    queue <int> q;  //没有队列那还叫广搜吗
    q.push(x);  //先把第一个顶点推进去,输出,标记访问过
    cout<<x<<" ";  
    vis2[x]=1; 
    while(!q.empty()){   //广搜板子,上!
        int fro=q.front();  //把队首取出来
        for(int i=0;i<e[fro].size();i++){   //每条边去试
            int point=s[e[fro][i]].v;  //取终点(和dfs差不多)
            if(!vis2[point]){  //没访问过,推进去,输出,标记
                q.push(point); 
                cout<<point<<" ";
                vis2[point]=1;
            }
        }
        q.pop();  //队首搜完啦!把它弄出去
    }
}

队列的作用就是将一个层次的节点给存入,先进先出的特点符合广度优先搜索的特点.

关于二叉树

www.luogu.com.cn/problem/P47…

二叉树的题目有关于很多都是关于排名的游戏,如果是遇到这种需要找到第一名是谁,第二名是谁的题目,可以使用队列来做,因为比赛总是从两个人中选择强的,也就是pop两个而push一个.

from queue import Queue
queue = Queue()
n = int(input())
m = list(map(int,input().split())) #输入数组
for i in range(len(m)):
    queue.put((m[i],i+1)) #第i位选手
​
while(queue.qsize()>2):    #如果只有两个
    x = queue.get()
    y = queue.get()
    if(x[0]>=y[0]):
        queue.put(x)
    else:
        queue.put(y)
​
x = queue.get()
y = queue.get()
if(x[0]>y[0]): #如果x[0]
    print(y[1])
else:
    print(x[1])  #为什么是滴

#### 5.数的划分

这个题主要是用搜索,构建一个函数纪录当前的遍历的数位置和使用的数的个数,当使用的数的个数等于k时,就判断与原来的数相等,相等就使方案加1,代码较简单

6.迷宫

www.luogu.com.cn/problem/P11…

这道题不同于其他的题目在于连通块的判断,首先我是用了一个递归进行赋值,但是出错的地方就在于不同方向的节点不相等,导致了WA,

关于深度优先搜索:

深度优先搜索写代码有两种,一种将判断条件写在最上层:

def dfs(value):
    if(seen[value]):    #如果已经访问过了 返回
        return
    seen[value]=True
    answer.append(value)
    for i in list1[value]:  #在列表中
        dfs(i)

如果只有一个起点开始的,可以将判断条件放在里面,但是使用上面那种更加通用

def dfs(value):            #
    seen[value]=True
    answer.append(value)
    for i in list1[value]:  #在列表中
        if(not seen[i]):    #如果已经访问过了 返回
            dfs(i)

关于广度优先搜索:

广度优先搜索都是用队列来写:

C语言的写完是这样的

void bfs(int x){   //bfs——广度优先遍历(x依然是第几号顶点,不过既然不递归其实传这个参数也没啥用)
    queue <int> q;  //没有队列那还叫广搜吗
    q.push(x);  //先把第一个顶点推进去,输出,标记访问过
    cout<<x<<" ";  
    vis2[x]=1; 
    while(!q.empty()){   //广搜板子,上!
        int fro=q.front();  //把队首取出来
        for(int i=0;i<e[fro].size();i++){   //每条边去试
            int point=s[e[fro][i]].v;  //取终点(和dfs差不多)
            if(!vis2[point]){  //没访问过,推进去,输出,标记
                q.push(point); 
                cout<<point<<" ";
                vis2[point]=1;
            }
        }
        q.pop();  //队首搜完啦!把它弄出去
    }
}

队列的作用就是将一个层次的节点给存入,先进先出的特点符合广度优先搜索的特点.

关于二叉树

www.luogu.com.cn/problem/P47…

二叉树的题目有关于很多都是关于排名的游戏,如果是遇到这种需要找到第一名是谁,第二名是谁的题目,可以使用队列来做,因为比赛总是从两个人中选择强的,也就是pop两个而push一个.

from queue import Queue
queue = Queue()
n = int(input())
m = list(map(int,input().split())) #输入数组
for i in range(len(m)):
    queue.put((m[i],i+1)) #第i位选手
​
while(queue.qsize()>2):    #如果只有两个
    x = queue.get()
    y = queue.get()
    if(x[0]>=y[0]):
        queue.put(x)
    else:
        queue.put(y)
​
x = queue.get()
y = queue.get()
if(x[0]>y[0]): #如果x[0]
    print(y[1])
else:
    print(x[1])  #为什么是滴

#### 5.数的划分

这个题主要是用搜索,构建一个函数纪录当前的遍历的数位置和使用的数的个数,当使用的数的个数等于k时,就判断与原来的数相等,相等就使方案加1,代码较简单

6.迷宫

www.luogu.com.cn/problem/P11…

这道题不同于其他的题目在于连通块的判断,首先我是用了一个递归进行赋值,但是出错的地方就在于不同方向的节点不相等,导致了WA,

关于深度优先搜索:

深度优先搜索写代码有两种,一种将判断条件写在最上层:

def dfs(value):
    if(seen[value]):    #如果已经访问过了 返回
        return
    seen[value]=True
    answer.append(value)
    for i in list1[value]:  #在列表中
        dfs(i)

如果只有一个起点开始的,可以将判断条件放在里面,但是使用上面那种更加通用

def dfs(value):            #
    seen[value]=True
    answer.append(value)
    for i in list1[value]:  #在列表中
        if(not seen[i]):    #如果已经访问过了 返回
            dfs(i)

关于广度优先搜索:

广度优先搜索都是用队列来写:

C语言的写完是这样的

void bfs(int x){   //bfs——广度优先遍历(x依然是第几号顶点,不过既然不递归其实传这个参数也没啥用)
    queue <int> q;  //没有队列那还叫广搜吗
    q.push(x);  //先把第一个顶点推进去,输出,标记访问过
    cout<<x<<" ";  
    vis2[x]=1; 
    while(!q.empty()){   //广搜板子,上!
        int fro=q.front();  //把队首取出来
        for(int i=0;i<e[fro].size();i++){   //每条边去试
            int point=s[e[fro][i]].v;  //取终点(和dfs差不多)
            if(!vis2[point]){  //没访问过,推进去,输出,标记
                q.push(point); 
                cout<<point<<" ";
                vis2[point]=1;
            }
        }
        q.pop();  //队首搜完啦!把它弄出去
    }
}

队列的作用就是将一个层次的节点给存入,先进先出的特点符合广度优先搜索的特点.

关于二叉树

www.luogu.com.cn/problem/P47…

二叉树的题目有关于很多都是关于排名的游戏,如果是遇到这种需要找到第一名是谁,第二名是谁的题目,可以使用队列来做,因为比赛总是从两个人中选择强的,也就是pop两个而push一个.

from queue import Queue
queue = Queue()
n = int(input())
m = list(map(int,input().split())) #输入数组
for i in range(len(m)):
    queue.put((m[i],i+1)) #第i位选手
​
while(queue.qsize()>2):    #如果只有两个
    x = queue.get()
    y = queue.get()
    if(x[0]>=y[0]):
        queue.put(x)
    else:
        queue.put(y)
​
x = queue.get()
y = queue.get()
if(x[0]>y[0]): #如果x[0]
    print(y[1])
else:
    print(x[1])  #为什么是滴

5.数的划分

这个题主要是用搜索,构建一个函数纪录当前的遍历的数位置和使用的数的个数,当使用的数的个数等于k时,就判断与原来的数相等,相等就使方案加1,代码较简单

6.迷宫

www.luogu.com.cn/problem/P11…

这道题不同于其他的题目在于连通块的判断,首先我是用了一个递归进行赋值,但是出错的地方就在于不同方向的节点不相等,导致了WA,

关于深度优先搜索:

深度优先搜索写代码有两种,一种将判断条件写在最上层:

def dfs(value):
    if(seen[value]):    #如果已经访问过了 返回
        return
    seen[value]=True
    answer.append(value)
    for i in list1[value]:  #在列表中
        dfs(i)

如果只有一个起点开始的,可以将判断条件放在里面,但是使用上面那种更加通用

def dfs(value):            #
    seen[value]=True
    answer.append(value)
    for i in list1[value]:  #在列表中
        if(not seen[i]):    #如果已经访问过了 返回
            dfs(i)

关于广度优先搜索:

广度优先搜索都是用队列来写:

C语言的写完是这样的

void bfs(int x){   //bfs——广度优先遍历(x依然是第几号顶点,不过既然不递归其实传这个参数也没啥用)
    queue <int> q;  //没有队列那还叫广搜吗
    q.push(x);  //先把第一个顶点推进去,输出,标记访问过
    cout<<x<<" ";  
    vis2[x]=1; 
    while(!q.empty()){   //广搜板子,上!
        int fro=q.front();  //把队首取出来
        for(int i=0;i<e[fro].size();i++){   //每条边去试
            int point=s[e[fro][i]].v;  //取终点(和dfs差不多)
            if(!vis2[point]){  //没访问过,推进去,输出,标记
                q.push(point); 
                cout<<point<<" ";
                vis2[point]=1;
            }
        }
        q.pop();  //队首搜完啦!把它弄出去
    }
}

队列的作用就是将一个层次的节点给存入,先进先出的特点符合广度优先搜索的特点.

关于二叉树

www.luogu.com.cn/problem/P47…

二叉树的题目有关于很多都是关于排名的游戏,如果是遇到这种需要找到第一名是谁,第二名是谁的题目,可以使用队列来做,因为比赛总是从两个人中选择强的,也就是pop两个而push一个.

from queue import Queue
queue = Queue()
n = int(input())
m = list(map(int,input().split())) #输入数组
for i in range(len(m)):
    queue.put((m[i],i+1)) #第i位选手
​
while(queue.qsize()>2):    #如果只有两个
    x = queue.get()
    y = queue.get()
    if(x[0]>=y[0]):
        queue.put(x)
    else:
        queue.put(y)
​
x = queue.get()
y = queue.get()
if(x[0]>y[0]): #如果x[0]
    print(y[1])
else:
    print(x[1])  #为什么是滴

6.迷宫

www.luogu.com.cn/problem/P11…

这道题不同于其他的题目在于连通块的判断,首先我是用了一个递归进行赋值,但是出错的地方就在于不同方向的节点不相等,导致了WA,

关于深度优先搜索:

深度优先搜索写代码有两种,一种将判断条件写在最上层:

def dfs(value):
    if(seen[value]):    #如果已经访问过了 返回
        return
    seen[value]=True
    answer.append(value)
    for i in list1[value]:  #在列表中
        dfs(i)

如果只有一个起点开始的,可以将判断条件放在里面,但是使用上面那种更加通用

def dfs(value):            #
    seen[value]=True
    answer.append(value)
    for i in list1[value]:  #在列表中
        if(not seen[i]):    #如果已经访问过了 返回
            dfs(i)

关于广度优先搜索:

广度优先搜索都是用队列来写:

C语言的写完是这样的

void bfs(int x){   //bfs——广度优先遍历(x依然是第几号顶点,不过既然不递归其实传这个参数也没啥用)
    queue <int> q;  //没有队列那还叫广搜吗
    q.push(x);  //先把第一个顶点推进去,输出,标记访问过
    cout<<x<<" ";  
    vis2[x]=1; 
    while(!q.empty()){   //广搜板子,上!
        int fro=q.front();  //把队首取出来
        for(int i=0;i<e[fro].size();i++){   //每条边去试
            int point=s[e[fro][i]].v;  //取终点(和dfs差不多)
            if(!vis2[point]){  //没访问过,推进去,输出,标记
                q.push(point); 
                cout<<point<<" ";
                vis2[point]=1;
            }
        }
        q.pop();  //队首搜完啦!把它弄出去
    }
}

队列的作用就是将一个层次的节点给存入,先进先出的特点符合广度优先搜索的特点.