Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 回溯-用硬币填充网格_C++_Algorithm_Backtracking - Fatal编程技术网

C++ 回溯-用硬币填充网格

C++ 回溯-用硬币填充网格,c++,algorithm,backtracking,C++,Algorithm,Backtracking,我试图回答我在查找面试问题时遇到的问题。我们被问及在n*m网格上放置r硬币的方法,以便每行和每列至少包含一枚硬币 我想到了一个回溯解决方案,以行的主要顺序处理网格中的每个单元格,我用这种方式设置了递归。似乎我的方法是错误的,因为它每次输出0。有人能帮我找出我的方法中的错误吗?谢谢 限制。n,m

我试图回答我在查找面试问题时遇到的问题。我们被问及在n*m网格上放置r硬币的方法,以便每行和每列至少包含一枚硬币

我想到了一个回溯解决方案,以行的主要顺序处理网格中的每个单元格,我用这种方式设置了递归。似乎我的方法是错误的,因为它每次输出0。有人能帮我找出我的方法中的错误吗?谢谢

限制。n,m<200,r 这是我想出的代码

#include<cstdio>
#define N 201
int n, m , r;
int used[N][N];
int grid[N][N] ;  // 1 is coin is placed . 0 otherwise. // -1 undecided.

bool isOk()
{
    int rows[N];
    int cols[N];

    for(int i = 0 ; i < n ; i++) rows[i] = 0;
    for(int i = 0 ; i < m ; i++) cols[i] = 0;
    int sum = 0;
    for(int i = 0 ; i < n ; i++)for(int j = 0; j < m ; j++)
    {
        if(grid[i][j]==1)
        {
            rows[i]++;
            cols[j]++;
            sum++;  
        }
    }
    for(int i = 0 ; i < n ; i++) 
    {
        if(rows[i]==0) return false;
    }

    for(int j = 0 ; j < n ; j++)
    {
        if(cols[j]==0) return false;
    }
    if(sum==r) return true;
    else return false;
}

int calc_ways(int row , int col,  int coins)
{
    if(row >= n) return 0;
    if(col >= m) return 0;
    if(coins > r) return 0;
    if(coins == r) 
    {
        bool res = isOk();
        if(res) return 1; 
        else 0;
    }

    if(row == n - 1 and col== m- 1) 
    {
        bool res = isOk();
        if(res) return 1;
        else return 0;
    }

    int nrow, ncol;

    if(col + 1 >= m)
    {
        nrow = row + 1;
        ncol = 0;
    }
    else
    {
        nrow = row;
        ncol = col + 1;
    }
    if(used[row][col]) return calc_ways(nrow, ncol, coins);
    int ans =  0;
    used[row][col] = 1;
    grid[row][col] = 0;
    ans += calc_ways(nrow , ncol , coins);

    grid[row][col] = 1;
    ans += calc_ways(nrow , ncol , coins + 1);

    return ans;
}

int main()
{
    int t;
    scanf("%d" , &t);
    while(t--)
    {
        scanf("%d %d %d" , &n , &m , &r);
        for(int i = 0 ; i <= n ; i++)
        {
            for(int j = 0; j <= m ; j++)
            {
                used[i][j] = 0;
                grid[i][j] = -1;
            }
        }
        printf("%d\n" , calc_ways(0  ,  0 , 0 ));
    }
    return 0;
}
#包括
#定义N 201
int n,m,r;
int使用[N][N];
整数网格[N][N];//1是硬币被放置。否则为0-1未决定。
bool isOk()
{
int行[N];
int cols[N];
对于(inti=0;i=n)返回0;
如果(col>=m)返回0;
如果(硬币>r)返回0;
如果(硬币==r)
{
bool res=isOk();
如果(res)返回1;
其余0;
}
如果(行==n-1,列==m-1)
{
bool res=isOk();
如果(res)返回1;
否则返回0;
}
int nrow,ncol;
如果(列+1>=m)
{
nrow=行+1;
ncol=0;
}
其他的
{
nrow=行;
ncol=col+1;
}
如果(使用[行][列])返回计算方式(nrow、ncol、硬币);
int ans=0;
使用的[行][列]=1;
网格[行][列]=0;
ans+=计算方式(nrow、ncol、硬币);
网格[行][列]=1;
ans+=计算方式(nrow、ncol、硬币+1);
返回ans;
}
int main()
{
int t;
scanf(“%d”、&t);
而(t--)
{
scanf(“%d%d%d”,&n,&m,&r);
对于(int i=0;i问题1
代码将首先在每个方块上放置一枚硬币,并将每个方块标记为已使用

然后,它将测试最终位置,并确定最终位置不符合r硬币的目标

下一步,它将开始回溯,但实际上永远不会尝试其他选择,因为used[row][col]设置为1,这会缩短放置硬币的代码

换句话说,一个问题是设置了“used”中的条目,但在递归过程中从未清除

问题2 代码的另一个问题是,如果n,m的大小为200,那么它将永远不会完成

问题是这种回溯代码的复杂性为O(2^(n*m)),因为它将尝试所有可能的硬币放置组合(n=m=200的许多宇宙寿命…)


我建议你看一个不同的方法。例如,你可能想考虑动态编程来计算有多少种方法将“K”硬币放置在板的“A”栏上,这样我们就可以把硬币放在“B”上。目前没有硬币的一排棋盘。

你几乎不需要一个程序来解决这个问题


在不丧失一般性的情况下,设m它可以被视为d网格b填充r硬币的总方式-(保留一行的总方式nd填充d rest-保留一列的总方式nd填充d rest-保留一行和一列的总方式nd填充d rest),这意味着

p(n*m ,r) -( (p((n-1)*m , r) * c(n,1)) +(p((m-1)*n , r) * c(m,1))+(p((n-1)*(m-1) , r) * c(n,1)*c(m,1)) )

我只是这么想,但不确定!

我会看看如何解决八皇后问题,然后将其修改为这个更通用的版本。可能是一个小错误,但在(int j=0;j
不应该是
m
而不是
n
吗?@jeffamaphone:你能详细解释一下这个评论吗?我真的不知道这会有什么用。@DesmondHume谢谢你。这不是我0输出的原因:)那么你是否建议当我检查r币的目标时,我应该使用[row][col col]失败?我根本不明白所用数组的用途。也许你可以删除所有对它的引用?我在做dp时遇到了麻烦。你能不能再详细说明一些提示???非常感谢。首先计算一下在一列中放置“x”硬币的方式。(有一个简单的表达式涉及阶乘。)经过思考,包含排除可能会更快,甚至可能有一个封闭式公式。如果您需要更多信息,我建议发布一个新问题,以便更多的人可以提供帮助(我想我在错误的时区有效地帮助您…)
p(n*m ,r) -( (p((n-1)*m , r) * c(n,1)) +(p((m-1)*n , r) * c(m,1))+(p((n-1)*(m-1) , r) * c(n,1)*c(m,1)) )