引入
题目描述
经典应用:八皇后问题
dg和udg数组的解释
对角线 d g [ u + i ] d g [ u + i ] dg[u+i]dg[u+i] dg[u+i]dg[u+i],反对角线 u d g [ n − u + i ] u d g [ n − u + i ] udg[n−u+i]udg[n−u+i] udg[n−u+i]udg[n−u+i]中的下标 u + i u+i u+i和 n − u + i n−u+i n−u+i 表示的是截距
下面分析中的 ( x , y ) (x,y) (x,y) 相当于上面的 ( u , i ) (u,i) (u,i)
反对角线 y = x + b y=x+b y=x+b, 截距 b = y − x b=y−x b=y−x,因为我们要把 b b b 当做数组下标来用,显然 b b b 不能是负的,所以我们加上 + n +n +n (实际上 + n + 4 +n+4 +n+4 , + 2 n +2n +2n都 行),来保证是结果是正的,即 y − x + n y-x+n y−x+n
而对角线 y = − x + b y=−x+b y=−x+b, 截距是 b = y + x b=y+x b=y+x,这里截距一定是非负的,所以不需要加偏移量
**核心目的:**找一些合法的下标来表示dgdg或udg是否被标记过,所以如果你愿意,你取 u d g [ n + n − u + i ] udg[n+n−u+i] udg[n+n−u+i] 也可以,只要所有 ( u , i ) (u,i) (u,i) 对可以映射过去就行
代码
#include <iostream>using namespace std;const int N = 20;int n;
char g[N][N];
bool col[N], dg[N], udg[N];void dfs(int u)
{if (u == n){for (int i = 0; i < n; i ++ ) puts(g[i]);puts("");return;}for (int i = 0; i < n; i ++ )if (!col[i] && !dg[u + i] && !udg[n - u + i]){g[u][i] = 'Q';col[i] = dg[u + i] = udg[n - u + i] = true;dfs(u + 1);col[i] = dg[u + i] = udg[n - u + i] = false;g[u][i] = '.';}
}int main()
{cin >> n;for (int i = 0; i < n; i ++ )for (int j = 0; j < n; j ++ )g[i][j] = '.';dfs(0);return 0;
}
例题
题目表述
Codeforce
代码
#include <iostream>
#include <cstring>
#include <algorithm>#define x first
#define y secondusing namespace std;typedef long long LL;
typedef pair<int, int> PII;const int N = 410;int T, n, m;
int a[N][N];
int l[N], r[N];int main()
{cin >> T;while(T -- ){memset(l, 0, sizeof l);memset(r, 0, sizeof r);cin >> n >> m;for(int i = 0; i < n; i ++ )for(int j = 0; j < m; j ++ ){cin >> a[i][j];l[i + j] += a[i][j];r[j - i + n] += a[i][j];}int res = -1;for(int i = 0; i < n; i ++ )for(int j = 0; j < m; j ++ ){//注意枚举到的枚举加了两次,还需要减去一次 res = max(res, l[i + j] + r[j - i + n] - a[i][j]);}cout << res << endl;} return 0;
}