题目

思路

完全模拟下棋,既没必要也不应该,因为终局一样就是同一个情况,不应该重复计数

坐标映射看这个:关于坐标压缩式子的解压缩式子-CSDN博客

注意这种错误,走分支直接上手修改数据,发现分支不合理竟然不是恢复再走其它分支,而是结束遍历。结果没回溯,且少遍历分支

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

const int N = 6;

int n = 5;
int r[N], c[N], dgn[N+N], xdgn[N+N]; //x+y<=10 x-y+5<=9
ll ans;

void dfs(int i, int j, int bk, int wh)
{
  if(j > n) {i++, j = 1;}
  if(i > n)
  {
      ans++;
      return;     
  }

  if(bk)
  {
    r[i]++, c[j]++, dgn[i+j]++, xdgn[i-j+n]++;
    if(r[i] == n || c[j] == n || dgn[i+j] == n || xdgn[i-j+n] == n) return;
    dfs(i, j+1, bk-1, wh);
    r[i]--, c[j]--, dgn[i+j]--, xdgn[i-j+n]--;
  }

  if(wh)
  {
    r[i]--, c[j]--, dgn[i+j]--, xdgn[i-j+n]--;
    if(r[i] == -n || c[j] == -n || dgn[i+j] == -n || xdgn[i-j+n] == -n) return;
    dfs(i, j+1, bk, wh-1);
    r[i]++, c[j]++, dgn[i+j]++, xdgn[i-j+n]++;
  }
}
int main()
{
  int bk = (n * n + 1) / 2, wh = n * n / 2; //黑先手,bk=13,wh=12
  dfs(1, 1, bk, wh); //从(1,1)开始
  printf("%lld", ans);
}

这个不行

这是正确做法,但是多一道恢复的语句

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

const int N = 6;

int n = 5;
int r[N], c[N], dgn[N+N], xdgn[N+N]; //x+y<=10 x-y+5<=9
ll ans;

void dfs(int i, int j, int bk, int wh)
{
  if(j > n) {i++, j = 1;}
  if(i > n)
  {
  	ans++;
  	return; 	
  }

  if(bk)
  {
    r[i]++, c[j]++, dgn[i+j]++, xdgn[i-j+n]++;
    if(r[i] == n || c[j] == n || dgn[i+j] == n || xdgn[i-j+n] == n) //不合理不递归,只恢复
    {
    	r[i]--, c[j]--, dgn[i+j]--, xdgn[i-j+n]--;
    }
    else //合理递归且恢复
    {
    	dfs(i, j+1, bk-1, wh);
    	r[i]--, c[j]--, dgn[i+j]--, xdgn[i-j+n]--;
    }
  }

  if(wh)
  {
    r[i]--, c[j]--, dgn[i+j]--, xdgn[i-j+n]--;
    if(r[i] == -n || c[j] == -n || dgn[i+j] == -n || xdgn[i-j+n] == -n)
    {
    	r[i]++, c[j]++, dgn[i+j]++, xdgn[i-j+n]++;
    }
    else
    {
    	dfs(i, j+1, bk, wh-1);
    	r[i]++, c[j]++, dgn[i+j]++, xdgn[i-j+n]++;
    }
  }
}
int main()
{
  int bk = (n * n + 1) / 2, wh = n * n / 2; //黑先手,bk=13,wh=12
  dfs(1, 1, bk, wh); //从(1,1)开始
  printf("%lld", ans);
}

另一种做法是直接试探合理性,不直接上手修改数据

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

const int N = 6;

int n = 5;
int r[N], c[N], dgn[N+N], xdgn[N+N]; //x+y<=10 x-y+5<=9
ll ans;

void dfs(int i, int j, int bk, int wh)
{
  if(j > n) {i++, j = 1;}
  if(i > n)
  {
  	ans++;
  	return; 	
  }

  if(bk)
  {
    
    if(r[i] + 1 < n && c[j] + 1 < n && dgn[i+j] + 1 < n && xdgn[i-j+n] + 1 < n) //试探
    {
    	r[i]++, c[j]++, dgn[i+j]++, xdgn[i-j+n]++;
    	dfs(i, j+1, bk-1, wh);
    	r[i]--, c[j]--, dgn[i+j]--, xdgn[i-j+n]--;
    }
  }

  if(wh)
  {
    
    if(r[i] - 1 > -n && c[j] - 1 > -n && dgn[i+j] - 1 > -n && xdgn[i-j+n] - 1 > -n)
    {
    	r[i]--, c[j]--, dgn[i+j]--, xdgn[i-j+n]--;
    	dfs(i, j+1, bk, wh-1);
    	r[i]++, c[j]++, dgn[i+j]++, xdgn[i-j+n]++;
    }
  }
}
int main()
{
  int bk = (n * n + 1) / 2, wh = n * n / 2; //黑先手,bk=13,wh=12
  dfs(1, 1, bk, wh); //从(1,1)开始
  printf("%lld", ans);
}

代码

#include<bits/stdc++.h>
using namespace std;
 
int row[20];
int col[20];
int dia[20]; //对角线
int ndia[20]; //反对角线
int result;
void dfs(int n, int white, int black) //white+1, black-1
{
    if(n == 26)
    {
        result++;
        return;
    }
 
    // int x = (n+5-1) / 5; //一维的n映射到二维的(x,y)
    // int y = n%5;
    // if(!y) y = 5;
    
    int x = (n-1)/5+1;
    int y = (n-1)%5+1;
 
    if(white && row[x] < 4 && col[y] < 4 && dia[x-y+5] < 4 && ndia[x+y] < 4)
    {
        row[x]++;
        col[y]++;
        dia[x-y+5]++;
        ndia[x+y]++;
        dfs(n+1, white-1, black);
        row[x]--;
        col[y]--;
        dia[x-y+5]--;
        ndia[x+y]--;
    }
    if(black && row[x] > -4 && col[y] > -4 && dia[x-y+5] > -4 && ndia[x+y] > -4)
    {
        row[x]--;
        col[y]--;
        dia[x-y+5]--;
        ndia[x+y]--;
        dfs(n+1, white, black-1);
        row[x]++;
        col[y]++;
        dia[x-y+5]++;
        ndia[x+y]++;
    }
 
    return;
}
int main()
{
    dfs(1, 13, 12);
 
    cout << result << endl;
 
    return 0;
}

重写

#include <bits/stdc++.h>
using namespace std;
const int N = 20;
int r[N], c[N], dg[N], xdg[N];
int n = 5, ans;
void dfs(int pos, int w, int b)
{
    if (pos == n * n + 1)
    {
        ans++;
        return;
    }

    int x = (pos - 1) / n + 1;
    int y = (pos - 1) % n + 1;

    if (w && r[x] < n - 1 && c[y] < n - 1 && dg[x + y] < n - 1 && xdg[x - y + n] < n - 1)
    {
        r[x]++;
        c[y]++;
        dg[x + y]++;
        xdg[x - y + n]++;
        dfs(pos + 1, w - 1, b);
        r[x]--;
        c[y]--;
        dg[x + y]--;
        xdg[x - y + n]--;
    }

    if (b && r[x] > 1 - n && c[y] > 1 - n && dg[x + y] > 1 - n && xdg[x - y + n] > 1 - n)
    {
        r[x]--;
        c[y]--;
        dg[x + y]--;
        xdg[x - y + n]--;
        dfs(pos + 1, w, b - 1);
        r[x]++;
        c[y]++;
        dg[x + y]++;
        xdg[x - y + n]++;
    }
}
int main()
{
    dfs(1, (n * n + 1) / 2, n * n / 2);
    cout << ans;
}

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐