uva 10401 Injured Queen Problem

來源:互聯網
上載者:User

原題:
Chess is a two-player board game believed to have been played in India as early as the sixth century. However, in this problem we will not discuss about chess, rather we will talk about a modified form of the classic n- queens problem. I know you are familiar with plotting n-queens on a chess board with the help of a classic backtracking algorithm. If you write that algorithm
now you will find that there are 92 ways of plotting 8 queens in an 8 × 8 board provided no queens attack each other.In this problem we will talk about injured queens who can move only like a king in horizontal and diagonal direction from current position but can reach any row from current position like a normal chess queen. You will have to find the number of possible arrangements with such injured queens in a particular (n× n) board (with some additional constraints),such that no two queens attack each other.

Fig: Injured Queen at a6 can reach the adjacent grey squares. Queen at e4 can reach adjacent grey
squares. The injured queen positions are black and the reachable places are grey.
Input
Input file contains several lines of input. Each line expresses a certain board status. The length of these
status string is the board dimension n (0 < n ≤ 15). The first character of the string denotes the status
of first column, the second character of the string denotes the status of the second column and so on.
So if the first character of the status string is 2, it means that we are looking for arrangements (no two
injured queen attack each other) which has injured queen in column a, row 2. The possible numbers
for rows are 1,2,3,…,D,E,F which indicates row 1, 2, 3… 13, 14, 15. If any column contains ‘?’
it means that in that column the injured queen can be in any row. So a status string ‘1?4??3 means
that you are asked to find out total number of possible arrangements in a (6 × 6) chessboard which
has three of its six injured queens at a1, c4 and f3. Also note that there will be no invalid inputs. For
example ‘1?51’ is an invalid input because a (4 × 4) chessboard does not have a fifth row.
Output
For each line of input produce one line of output. This line should contain an integer which indicates
the total number of possible arrangements of the corresponding input status string.
Sample Input
??????
???????????????
???8?????
43?????
Sample Output
2642
22696209911206174
2098208
0
大意:
給你一個n×n的棋盤,現在讓你在棋盤上面放上一個受傷的皇后。每個皇后的攻擊範圍如圖片所示,現在問你一個n×n大小的棋盤有多少种放置方法。給你一個字串,代表每列的狀態,如果字元為’?’表示該列是空的,可以隨便放,如果是個數字表示該列已經有一個受傷的皇后。

//狀態壓縮代碼#include <bits/stdc++.h>using namespace std;//fstream in,out;long long dp[16][32770];string s;int GetNum(char c){    if(c>='1'&&c<='9')        return c-'0';    else        return c-'A'+10;}bool cmp(int a,int b){    if(a==b)        return false;    if(a<<1==b)        return false;    if(a>>1==b)        return false;    return true;}int main(){    ios::sync_with_stdio(false);    int n;    while(cin>>s)    {        memset(dp,0,sizeof(dp));        int len=s.size();        if(s[0]=='?')            for(int i=0;i<len;i++)                dp[0][1<<i]=1;        else            dp[0][1<<(GetNum(s[0])-1)]=1;        for(int i=1;i<len;i++)        {            if(s[i]=='?')            {                for(int j=0,pj=1;j<len;++j,pj=1<<j)                {                    if(s[i-1]=='?')                    {                        for(int k=0,pk=1;k<len;++k,pk=1<<k)                            if(cmp(pj,pk))                                dp[i][pj]+=dp[i-1][pk];                    }                    else                    {                        int pk=1<<(GetNum(s[i-1])-1);                        if(cmp(pj,pk))                            dp[i][pj]+=dp[i-1][pk];                    }                }            }            else            {                int pj=1<<(GetNum(s[i])-1);                if(s[i-1]=='?')                {                    for(int k=0,pk=1;k<len;++k,pk=1<<k)                        if(cmp(pj,pk))                            dp[i][pj]+=dp[i-1][pk];                }                else                {                    int pk=1<<(GetNum(s[i-1])-1);                    if(cmp(pj,pk))                        dp[i][pj]+=dp[i-1][pk];                }            }        }        long long ans=0;        for(int i=0,pi=1;i<len;++i,pi=1<<i)            ans+=dp[len-1][pi];        cout<<ans<<endl;    }    return 0;}
//正常代碼#include <bits/stdc++.h>using namespace std;//fstream in,out;long long dp[16][16];string s;int GetNum(char c){    if(c>='1'&&c<='9')        return c-'0';    else        return c-'A'+10;}bool cmp(int a,int b){    if(a==b)        return false;    if(a+1==b)        return false;    if(a-1==b)        return false;    return true;}int main(){    ios::sync_with_stdio(false);    int n;    while(cin>>s)    {        memset(dp,0,sizeof(dp));        int len=s.size();        if(s[0]=='?')            for(int i=0;i<len;i++)                dp[0][i]=1;        else            dp[0][GetNum(s[0])-1]=1;        for(int i=1;i<len;i++)        {            if(s[i]=='?')            {                for(int j=0;j<len;++j)                {                    if(s[i-1]=='?')                    {                        for(int k=0;k<len;++k)                            if(cmp(j,k))                                dp[i][j]+=dp[i-1][k];                    }                    else                    {                        int k=GetNum(s[i-1])-1;                        if(cmp(j,k))                            dp[i][j]+=dp[i-1][k];                    }                }            }            else            {                int j=GetNum(s[i])-1;                if(s[i-1]=='?')                {                    for(int k=0;k<len;++k)                        if(cmp(j,k))                            dp[i][j]+=dp[i-1][k];                }                else                {                    int k=GetNum(s[i-1])-1;                    if(cmp(j,k))                        dp[i][j]+=dp[i-1][k];                }            }        }        long long ans=0;        for(int i=0;i<len;++i)            ans+=dp[len-1][i];        cout<<ans<<endl;    }    return 0;}

解答:
最近剛看了狀態壓縮的動態規劃,看到這道題就想用狀態壓縮的方法解決出來。不過因為一個皇后可以攻擊一整列,所以一列只能放一個皇后,所以用不上狀態壓縮來表示的每行。 不過這道題練習一下狀態壓縮入門還是挺好的。
轉移方程也非常簡單,dp[i][j]+=dp[i-1][k]表示的是第i列放置第j行有多少种放置方法,其中要判斷一下j和k是否衝突,也就是j和k是否能互相攻擊到。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.