题目
思路
完全模拟下棋,既没必要也不应该,因为终局一样就是同一个情况,不应该重复计数
坐标映射看这个:关于坐标压缩式子的解压缩式子-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;
}