2190: 【递归】冲突 dfs+小技巧

题目描述
监狱的每间牢房是一个不超过4×4的正方形,里面设有一些障碍,牢房里住着的犯人脾气都很大,只要两个犯人位于同一行或同一列即会发生冲突,但障碍物可以阻挡同行或同列犯人的冲突。问最多可放几个犯人而不会发生冲突。如下图所示,左边表示初始牢房样,右边4个显示了摆放方案,当然,最后两个方案是错误的。

输入
有多组测试数据,每组数据第一行为一个整数N表示牢房大小。随后N行描述牢房,其中X表示障碍。

所有测试数据结束的标志为0。
输出
输出最多可放的犯人数。
3
.X.
X.X
.X.
3

.XX
.XX
4




0
样例输出 Copy
5
1
5
2
4

这道入门+的搜索题,博主不久前做了道补全数独的题,第一反应就是每个点都尝试放人,也就是改成R,然后行和列分别用一位数组判断是否冲突(类似数独规则)。
最关键的小技巧:如果走到墙,便将这个点横向和纵向对应的数组元素恢复为0,实现了墙格挡冲突的效果(想一想为什么)。

答案是走的顺序是从左往右,从上往下,之后尝试放在同一行的犯人,必定在之前霸占该行的犯人的右边,同理,之后尝试放同一列的犯人必定在之前霸占该列的犯人的下边,遇到墙取消霸占(数组该位回归0)

贴代码:

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
char fie[5][5],q[5][5];
int n,ans,sum,f;
int row[5],line[5];//储存行列霸王是否存在的数组
void dfs(int x,int y)
{
    
    
    for(int i = y; i<=n; i++)
    {
    
    
        if(q[x][y]=='.'&&fie[x][y]=='.'&&!row[x]&&!line[y])
        {
    
    
            fie[x][y]='R';//放人
            row[x]=1;//霸
            line[y]=1;//霸
        }
        else if(q[x][y]=='X')
        {
    
    
            row[x]=line[y]=0;//回归0
        }
        else if(fie[x][y]=='R')continue;
        if(x==n&&y==n)//走到最后,判断放的人数(R的数量)
        {
    
    
            for(int i = 1; i<=n; i++)
            {
    
    
                for(int j = 1; j<=n; j++)
                {
    
    
                    if(fie[i][j]=='R')
                    {
    
    
                        sum++;
                    }
                }
            }
            ans=max(ans,sum);
            sum=0;
            return;
        }
        else if(y==n)
        {
    
    
            dfs(x+1,1);//往右走
            fie[x][y]='.';//回溯
            return;
        }
        else
        {
    
    
            dfs(x,y+1);//往左走
            fie[x][y]='.';//回溯
            return;
        }
    }
}
int main()
{
    
    
    while(cin>>n&&n)
    {
    
    
        ans=0;
        for(int i = 1; i<=n; i++)
        {
    
    
            for(int j = 1; j<=n; j++)
            {
    
    
                cin>>q[i][j];
            }
        }
        for(int i = 1; i<=n; i++)
        {
    
    
            for(int j = 1; j<=n; j++)
            {
    
    
                sum=0;
                memset(fie,'.',sizeof(fie));
                memset(row,0,sizeof(row));
                memset(line,0,sizeof(line));//每个点判断前都要初始化
                dfs(i,j);
            }
        }
        cout<<ans<<endl;
    }
 
    return 0;
}

小白大一博主,希望对您有帮助。

猜你喜欢

转载自blog.csdn.net/qq_51152918/article/details/111592768