tema
Dada una imagen de 8 * 8, hay 8 reinas en ella, ahora solo puedes mover una reina en cualquier momento en la misma dirección, hay un total de 8 direcciones; pregunta cuántos pasos se requieren al menos para que todas las reinas no se atacaran el uno al otro lado?
Ideas
Una incursión pura no funcionará, explotará en el tiempo y el espacio.
Si sabemos dónde debería estar cada reina al final, y luego calculamos el número mínimo de pasos, será mucho más sencillo. Aquí podemos usar la presión del estado para hacerlo;
porque la situación final es que hay una reina en cada línea. , por lo que no necesito registrar cada línea. La columna donde se encuentra la reina, y luego enumerar qué reina mover a esta posición;
dp [sta] [fila], lo que significa que el estado al considerar la fuente de la la reina en la fila fila es sta, y luego intentamos poner sta & (1 << i) == 1, es decir, la i-ésima reina en la imagen original se mueve a la posición de la reina en la fila de la fila; la complejidad total aquí es 8 ∗28 ;
Entonces solo queremos conocer todas las situaciones legales, buscar 92 tipos de situaciones legales,
finalmente, ejecutar la presión estatal para cada situación y tomar el mínimo de todas las situaciones;
题目中有说两个皇后不能同时出现在一个格子里面,在移动过程中会出现相遇的情况;但是通过不同移动的先后顺序是可以避免相遇的情况的;
int p[110][10]; // p[cnt][row] = col;第cnt张图的第row行的Queen在col列
int tp[10]; // tp[row] = col;当前图的row行的Queen在col列
int dp[1 << 9][10]; // dp[sta][row];
int x[10], y[10]; // the position of eight queen;
int cnt;
void dfs(int row) {
if (row == 8) {
for (int i = 0;i < 8;++i)
p[cnt][i] = tp[i];
++cnt;
return ;
}
// 枚举第row行的Queen在col列,再判断可行性
for (int col = 0;col < 8;++col) {
bool ok = true;
for (int i = 0;i < row;++i) {
if (col == tp[i] || tp[i] + i == row + col || tp[i] - i == col - row) {
ok = false;
break;
}
}
if (ok){
tp[row] = col;
dfs(row + 1);
}
}
}
int getdis(int cur, int num, int i) {
//这儿abs很重要
int t1 = abs(x[i] - num);
int t2 = abs(y[i] - p[cur][num]);
int res = 0;
if (min(t1, t2) != 0) res++;
if (abs(t1 - t2) != 0) res++;
return res;
}
int go(int cur, int num, int sta) {
if (num == 0) return 0;
if (dp[sta][num] != -1) return dp[sta][num];
int tans = inf;
for (int i = 0;i < 8;++i) {
if (sta & (1 << i)) {
// 对于第cur张图而言,把第i个Queen放在这张图第(num - 1)行Queen所在的位置
tans = min(tans, getdis(cur, num - 1, i) + go(cur, num - 1, sta ^ (1 << i)) );
}
}
return dp[sta][num] = tans;
}
int solve() {
int ans = inf;
for (int i = 0;i < cnt;++i) {
memset(dp, -1, sizeof dp);
ans = min(ans, go(i, 8, (1 << 8) - 1));
}
return ans;
}
int main(int argc, const char * argv[])
{
dfs(0);
int kase;cin >> kase;
while(kase--) {
int t = 0;
for (int i = 0;i < 8;++i) {
char s[10];scanf("%s", s);
for (int j = 0;j < 8;++j) {
if (s[j] == 'q') {
x[t] = i;
y[t] = j;
++t;
}
}
}
int ans = solve();
printf("Case %d: %d\n", ++nCase, ans);
}
return 0;
}