您的位置:首页 > 产品设计 > UI/UE

uva 10401 Injured Queen Problem

2016-03-02 11:58 459 查看
原题:

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是否能互相攻击到。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: