有没有办法让骑士们坐在圆桌旁,让每个骑士都坐在他的朋友旁边?

问题描述 投票:0回答:1

我在进行一些编码挑战时偶然发现了这个问题:

圆桌位于一个巨大的大厅里,周围有N张椅子。每个骑士都想坐在他的朋友附近,否则他拒绝坐。
第一行给出一个整数 n,其中 n 是圆桌骑士的数量 ( 3<=n<=100 ). The knights are numbered from 1 to n. Each of the following n lines contains a sequence of n values 0 or 1, separated by a space. The ith sequence shows the friendship relations of the ith knight. The jth value determines if the ith knight is a friend of the jth knight. They are friends if the value is 1, and not friends if the value is 0. Since friendship is reciprocal, if I is a friend of j, j is also friend of i.
输出
如果骑士们可以围坐在圆桌旁,则显示“是”,否则显示“否”。

根据我的理解,我们得到了一个基本上是无向图的邻接矩阵,其中节点是骑士,边代表友谊关系。现在我的想法是在图中搜索长度为 N 的循环,或哈密顿循环。如果是这样,则输出 YES,否则输出 NO。

我的代码确实适用于所提供的基本示例,但不知何故,它在 N 足够大的某个测试中失败了。 (注意是错误答案,不是Time Limit错误)

这是我的代码:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

void dfs_search(vector<vector<int> > &matrix, vector<bool> &visited, int node, int parent, int n, int path, bool &found){
    if(found)
        return;
    else if(visited[node] && node == parent && path == n){
        found = 1;
        return;
    }
    else if(visited[node])
        return;
    else{
        visited[node] = 1;
        path++; 
        //cout<<node<<" "<<path<<endl;
        
        for(int i=0; i < n; i++){
            if(matrix[node][i] == 1){
                dfs_search(matrix, visited, i, parent, n, path, found);
            }
        }

        visited[node] = 0;
        path--;
    }

}
int main(){

    int n;

    cin >> n;

    bool found = 0;

    vector<vector<int> > matrix(n, vector<int>(n));
    vector<bool> visited(n, 0);

    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++)
            cin>>matrix[i][j];
    }

    for(int i=0; i<n; i++){
        dfs_search(matrix, visited, i, i, n, 0, found);
        if(found){
            break;
        }
    }
    
    if(found)
        cout<<"YES";
    else
        cout<<"NO";

    return 0;
}

我是否遗漏了一些完全明显的东西,这些东西会使我的代码在输入更大的情况下失败。还是我遗漏了任何需要处理的特殊情况?

如有任何提示,我将不胜感激。预先感谢!

输入示例:

5
0 1 1 0 1
1 0 0 1 1
1 0 0 1 1
0 1 1 0 1
1 1 1 1 0

输出示例:

c++ graph cycle
1个回答
0
投票

一般来说,最好为您的图表使用标准库。如果您每次都从头开始编写顶点和边数据结构,您将失去效率并花费一半的时间来调试图结构,而不是您的算法。

一般来说,我避免使用递归函数,因为它们不能扩展到大图。在这种情况下,递归函数对于跟踪路径长度非常方便,所以让我们继续使用它。最小化递归函数的参数非常重要,以免耗尽堆栈内存。因此,使递归函数成为类方法,并将尽可能多的参数移动到类属性中。

像这样:

#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
#include "cGraph.h" // https://github.com/JamesBremner/PathFinder

class cSeatFinder
{

public:
    void generateExample1();

    void arrangeSeating();

private:

    raven::graph::cGraph g;

    std::vector<bool> visited;

/**
 * @brief Determine if the there is a cycle that includes every node
 * 
 * @param node current node being explored
 * @param pathlength length of path to current node from start
 * 
 * Recursive.  Assumes starting node has id 0
 * 
 * If full cycle found, throws an exception std::runtime_error("found seating");
 * If not found, returns to caller
 */
    void dfs_full_cycle(
        int node,
        int pathlength);
};

void cSeatFinder::generateExample1()
{
    g.add(0, 1);
    g.add(0, 2);
    g.add(0, 4);
    g.add(1, 3);
    g.add(1, 4);
    g.add(2, 3);
    g.add(2, 4);
    g.add(3, 4);
}

void cSeatFinder::dfs_full_cycle(
    int node,
    int pathlength)
{

    // check if we have returned to the start
    if ( node == 0 ) {
        
        // check if we have visited every node
        if( pathlength == g.vertexCount()) {

            throw std::runtime_error("found seating");
        }
    }

    if (visited[node])
        return;

    visited[node] = 1;
    pathlength++;

    for (int vi : g.adjacentOut(node))
        dfs_full_cycle( vi, pathlength );

    visited[node] = 0;
    pathlength--;
}
void cSeatFinder::arrangeSeating()
{
    visited.resize(g.vertexCount(), false);
    try
    {
        dfs_full_cycle( 0, 0 );
    }
    catch (std::runtime_error &e)
    {
        if (e.what() == std::string("found seating"))
        {
            std::cout << "YES\n";
            return;
        }
    }

    std::cout << "NO\n";
}

main()
{
    cSeatFinder theSeatFinder;

    theSeatFinder.generateExample1();

    theSeatFinder.arrangeSeating();

    return 2;
}
© www.soinside.com 2019 - 2024. All rights reserved.