sjtu2018-棋盘遍历问题

题意理解:若存在一种搜索路径,使起点被遍历两次,其他所有节点被遍历一次,则返回Y

大体思路:

用isvalid数组存储每个点是否被搜索过,用sum来标志棋盘还有多少点没有被搜索。

从起点开始深度优先搜索,终止条件是搜索到起点且sum==0。若搜索到非法点或者已经遍历过的点,则剪枝。

注意回溯之后的恢复现场!

在main函数中,可以提前判断:

若棋盘面积为1,则返回Y

若行数或列数为1,则返回N


C++代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
int n,m;
const int N=15;
bool isvalid[N][N];
int sum;//表示棋盘总数
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};

bool dfs(int x,int y)
{
    if(x==0&&y==0&&sum==0) return true;//走到起点且遍历了整个棋盘

    if(x<0||x>=n||y<0||y>=m||isvalid[x][y]) return false;//走到非法点或者该点已经遍历过


    //加入搜索路径
    isvalid[x][y]=true;
    sum--;

    //向四周搜索
    for(int i=0;i<4;i++)
    {
        int newx=x+dx[i],newy=y+dy[i];
        if(dfs(newx,newy))
            return true;

    }
    //回溯之后恢复现场
    isvalid[x][y]=false;
    sum++;

    return false;//该点加入搜索路径后不能完成任务,返回false
}




int main()
{
    while(cin>>n>>m)
    {
        memset(isvalid,0,sizeof isvalid);
        sum=n*m;

        if(sum==1)//棋盘大小为1
        {
            puts("Y");
            continue;
        }

        if(n==1||m==1&&sum!=1)//棋盘只有1行或1列
        {
            puts("N");
            continue;
        }

        if(dfs(0,0))    puts("Y");

        else puts("N");
    }

    return 0;
}


奇技淫巧: 观察可以发现

  • 若棋盘面积为1,则满足题意
  • 若棋盘行/列值不全为奇数,也可以满足题意
  • 若棋盘行/列值全为奇数,则不满足题意
  • 若棋盘为行数==1||列数==1,不满足题意

则可以得到:

#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
int n,m;

int main()
{
    while(cin>>n>>m)
    {
        if(n*m==1) puts("Y");

        else if((n==1||m==1)&&n*m!=1) puts("N");

        else if(n%2&&m%2) puts("N");

        else puts("Y");
    }

    return 0;
}
全部评论

相关推荐

犹豫的小狐狸刷了100道题:你是我在牛课上见到的最漂亮的女孩了
点赞 评论 收藏
分享
Southyeung:我说一下我的看法(有冒犯实属抱歉):(1)简历不太美观,给我一种看都不想看的感觉,感觉字体还是排版问题;(2)numpy就一个基础包,机器学习算法是什么鬼?我感觉你把svm那些写上去都要好一点。(2)课程不要写,没人看,换成获奖经历;(3)项目太少了,至少2-3个,是在不行把网上学习的也写上去。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务