17080 拉丁矩阵问题 【回溯法 记忆化搜索】

在这里插入图片描述
基本思路:每行进行全排列,与前面的字典序全排列的一个不同就是这里的visited[][]数组要开成二维的,一个Visited[row][i]记录行里面的用过的数,另外一个Visited[i][col]用来记录列里面,确保无重复。同时,边界多了一种列到边界行没到的情况,这时候要继续traceback,只是列参数变为0,行参数+1。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int m, n;
int count=0;
int a[100][100];
int visited[100][100];
int visited1[100][100];
int ok(int i, int j)
{
    int flag=1;
    int x,y;
    for(x=0;x<i;x++)
    {
        if(a[x][j]==a[i][j])
        {
            flag=0;
            break;
        }
    }
     for(y=0;y<j;y++)
    {
        if(a[i][y]==a[i][j])
        {
            flag=0;
            break;
        }
    }
    return flag;

}

void traceback(int x, int y)
{

    if(x==m-1&&y==n)
    {
        // printf("wa\n");
        count++;
        return ;
    }
    else if(y==n)
    {

        traceback(x+1,0);
    }


    int i, j;  int temp;
    for(i=1;i<=n;i++)
    {
       if(!visited[x][i]&&!visited1[i][y])
       {
           visited[x][i]=1; visited1[i][y]=1;
           traceback(x,y+1);
          visited[x][i]=0; visited1[i][y]=0;
       }


    }



}


int main()
{

    scanf("%d%d",&m,&n);
    memset(visited,0,sizeof(visited));
    memset(visited1,0,sizeof(visited1));
    traceback(0,0);
    printf("%d\n",count);
    return 0;
}

发布了33 篇原创文章 · 获赞 23 · 访问量 1837

猜你喜欢

转载自blog.csdn.net/qq_45492531/article/details/103340575