您的位置:首页 > 其它

Acdream 1132 Chess(状压dp)

2015-04-16 18:19 477 查看


Chess

Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others)

Submit Statistic Next
Problem


Problem Description

Xiang-qi is a kind of traditional Chinese chess. There is a special role in the game called “Jiang” (or called “Shuai”). When you want to operate this kind of role, it can only dominating
the four neighbor cell and can of course attack the role there (In fact there is a special condition can allow the role attack farther distance but we ignore this condition).
Now we have an N*N chessboard, we want to place some “Jiang” on it. Of course we have several restraints on placing chess pieces:
1. The placing chess role cannot dominate each other.

2. On the chessboard all cells without placing chess should be dominated.

3. There are some cells called “Hole” which cannot be placed by chess piece. Attention that the hole should also be dominated.
For a given chessboard, we want to know the least number of chess pieces to place which can satisfy the restraints above.


Input

There are multiple test cases.
In each test case, the first line contains two integers N and K indicating the size of the chessboard and the number of the holes on the chessboard. (1 <= N <= 9, 0 <= K <= N*N)
In the next K line each line contains two integers x and y indicating the cell (x, y) is a hole cell. (1 <= x, y <= N)
You can get more details from the sample and hint.


Output

For each test case, you should output an integer indicating the answer of the test case. If there is no way to place the chess pieces, please output -1.


Sample Input

3 2
1 1
3 3



Sample Output

3



Hint

In the sample we can have several ways to placing the chess pieces:
Place on (1, 3), (2, 1) and (3, 2);

Place on (3, 1), (1, 2) and (2, 3);
Although place on (1, 2), (2, 2) and (3, 2) can dominate all cell but it is not satisfy the first restraint. And place on (1, 1), (1, 3) and (3, 2) is also illegal because the cell (1, 1) is a hole.

题目链接:http://acdream.info/problem?pid=1132

//dp[i][cur][up] 代表 i行 type[cur]状态,i-1行是type[up]时放的棋子数目

//思路:先预处理哪一些状态没有相邻的1, 状态中1代表放了  将  ,
//因为放第i行时当前状态不能喝hole冲突,且不能喝i-1行状态冲突,且必须使得i-1行中的格子都要被控制,
//而i-1行被控制的状态与i-2也有关,所以也要记录i-2行的状态,所以用3维dp

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>

#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define MID(x,y) ((x+y)>>1)

#define eps 1e-8
//typedef __int64 ll;

#define fre(i,a,b)  for(i = a; i < b; i++)
#define frer(i,a,b) for(i = a; i > =b;i--)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define ssf(n)      scanf("%s", n)
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define bug         pf("Hi\n")

using namespace std;

#define INF 0x3f3f3f3f
#define N 520

int dp[10]

;
int type
,k;
int n,m,h[10],num
;

int lowbit(int x)     //计算x状态1的数目
{
	int t=0;
	while(x)
	{
		t++;
		x&=(x-1);
	}
   return t;
}

bool ok(int x)
{
	if(x&(x<<1)) return false;
	return true;
}

void inint()       //预处理每一行没有相邻的11状态
{
	int i,j;
	int len=1<<n;
	k=0;
	fre(i,0,len)
	 if(ok(i))
		type[k++]=i;

	fre(i,0,k)
	  num[i]=lowbit(type[i]);    //求出这一种状态的1的数目
}

void solve()
{
     int i,j,cur,up,uup;
     fre(i,2,n)
       fre(cur,0,k)      //当前状态
       {
       	   if(type[cur]&h[i]) continue;

       	   fre(up,0,k)         //上一行状态
       	   {
       	   	  if(type[up]&h[i-1]) continue;
       	   	  if(type[up]&type[cur]) continue;

       	   	  fre(uup,0,k)       //上上一行状态
       	   	  {
       	   	      if(type[uup]&h[i-2]) continue;
       	   	      if(type[uup]&type[up]) continue;
                  if(!dp[i-1][up][uup]) continue;
       	   	      int t=type[up]|(type[up]<<1)|(type[up]>>1);
       	   	      t|=type[uup];
       	   	      t|=type[cur];
       	   	      t&=(1<<n)-1;    //这一步很重要,bug半天
       	   	      if(t!=(1<<n)-1) continue;
       	   	      dp[i][cur][up]=min(dp[i][cur][up],dp[i-1][up][uup]+num[cur]);
       	   	  }
       	   }
       }
	int ans=INF;

	fre(i,0,k)
	 fre(up,0,k)
	 {
	 	if(dp
[i][up]==INF)  continue;
	 	if(h
&type[i]) continue;
	 	if(h[n-1]&type[up]) continue;
	 	if(type[i]&type[k]) continue;
	 	int t=type[i]|(type[i]<<1)|(type[i]>>1);
	 	t|=type[up];
	 	t&=(1<<n)-1;
	 	if(t!=(1<<n)-1) continue;
	 	if(!dp
[i][up]) continue;
	 	ans=min(ans,dp
[i][up]);
	 }
     if(ans==INF) ans=-1;
     printf("%d\n",ans);
}

int main()
{
    int i,j;
    while(~sff(n,m))
	{
       inint();
       mem(h,0);
       int x,y;
       while(m--)
	   {
	   	  sff(x,y);
	   	  h[x]|=1<<(y-1);
	   }

       mem(dp,0);

       fre(i,0,k)
         {
         	if(type[i]&h[1]) continue;
         	dp[1][i][0]=num[i];
         }
	solve();
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: