LightOJ 1061 N Queen Again (search + state pressure DP)

topic

Given an 8*8 picture, there are 8 queens on it, now you can only move one queen at any time in the same direction, there are 8 directions in total; ask how many steps are the minimum required so that all the queens will not attack each other other side?

Ideas

A pure raid will not work, it will explode in time and space.
If we know where each queen should be in the end, and then calculate the minimum number of steps, it will be much simpler. Here we can use state pressure to do it;
because the final situation is that there is a queen in each row, so I don’t need to record each row. The column where the queen is located, and then enumerate which queen to move to this position;
dp[sta][row], which means that the state when considering the source of the queen in row row is sta, and then we try to put sta & (1 << i) == 1, that is, the i-th queen in the original picture moves to the position of the queen in the row row; the total complexity here is 828 ;
Then we just want to find out all the legal situations, search for 92 kinds of legal situations;
finally, run the state pressure for each situation and take the minimum of all the situations;

题目中有说两个皇后不能同时出现在一个格子里面,在移动过程中会出现相遇的情况;但是通过不同移动的先后顺序是可以避免相遇的情况的;
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;
}

Guess you like

Origin blog.csdn.net/KIJamesQi/article/details/55519777