Acdream 1132 Chess(状压dp)

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][N][N];
int type[N],k;
int n,m,h[10],num[N];

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[n][i][up]==INF)  continue;
	 	if(h[n]&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[n][i][up]) continue;
	 	ans=min(ans,dp[n][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;
}
时间: 2024-10-19 15:41:37

Acdream 1132 Chess(状压dp)的相关文章

acdream 1409 Musical 状压DP

链接:http://acdream.info/problem?pid=1409 题意:整个国家有n座城市,每座城市有三种粉丝. 第一种一周看一场音乐剧,挑选的音乐剧是已经在周围城市播放上演过的次数最多的音乐剧中的随机一个. 第二种每天看一场音乐剧,挑选的是在本城市上映的音乐剧中的随机一个. 第三种每天看一场音乐剧,挑选的是在本城市以及周围城市中上映的音乐剧中的随机一个. 周围的城市是指这座城市与当前城市之间存在路径. 我现在要带着一部音乐剧环游全国(可以坐飞机,不用走路径),每座城市呆一周,并且

ZOJ3305Get Sauce 状压DP,

状压DP的题目留个纪念,首先题意一开始读错了,搞了好久,然后弄好了,觉得DFS可以,最后超时,修改了很久还是超时,没办法看了一下n的范围,然后觉得状压可以,但是没有直接推出来,就记忆化搜索了一下,可是一直错,莫名奇妙,然后没办法看了一下题解,发现了下面这个比较好的方法,然后按照这个方程去推,然后敲,也是WA了好多把,写的太搓了,没人家的清楚明了,唉~也算是给自己留个纪念,状压一直做的都不太好~唉~还好理解了, 参考了  http://blog.csdn.net/nash142857/articl

poj 2411 Mondriaan&#39;s Dream(状压DP)

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12232   Accepted: 7142 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

(状压dp)uva 10817 Headmaster&#39;s Headache

题目地址 1 #include <bits/stdc++.h> 2 typedef long long ll; 3 using namespace std; 4 const int MAX=1e5+5; 5 const int INF=1e9; 6 int s,m,n; 7 int cost[125]; 8 //char sta[MAX]; 9 string sta; 10 int able[125]; 11 int dp[125][1<<8][1<<8]; 12 in

HDU5816 Hearthstone(状压DP)

题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5816 Description Hearthstone is an online collectible card game from Blizzard Entertainment. Strategies and luck are the most important factors in this game. When you suffer a desperate situation an

HDU 4336 容斥原理 || 状压DP

状压DP :F(S)=Sum*F(S)+p(x1)*F(S^(1<<x1))+p(x2)*F(S^(1<<x2))...+1; F(S)表示取状态为S的牌的期望次数,Sum表示什么都不取得概率,p(x1)表示的是取x1的概率,最后要加一因为有又多拿了一次.整理一下就可以了. 1 #include <cstdio> 2 const int Maxn=23; 3 double F[1<<Maxn],p[Maxn]; 4 int n; 5 int main() 6

Travel(HDU 4284状压dp)

题意:给n个城市m条路的网图,pp在城市1有一定的钱,想游览这n个城市(包括1),到达一个城市要一定的花费,可以在城市工作赚钱,但前提有工作证(得到有一定的花费),没工作证不能在该城市工作,但可以走,一个城市只能工作一次,问pp是否能游览n个城市回到城市1. 分析:这个题想到杀怪(Survival(ZOJ 2297状压dp) 那个题,也是钱如果小于0就挂了,最后求剩余的最大钱数,先求出最短路和 Hie with the Pie(POJ 3311状压dp) 送披萨那个题相似. #include <

BZOJ 1087: [SCOI2005]互不侵犯King( 状压dp )

简单的状压dp... dp( x , h , s ) 表示当前第 x 行 , 用了 h 个 king , 当前行的状态为 s . 考虑转移 : dp( x , h , s ) = ∑ dp( x - 1 , h - cnt_1( s ) , s' ) ( s and s' 两行不冲突 , cnt_1( s ) 表示 s 状态用了多少个 king ) 我有各种预处理所以 code 的方程和这有点不一样 ------------------------------------------------

BZOJ 1072 排列 状压DP

题意:链接 方法:状压DP? 题解:这题其实没啥好写的,不算很难,推一推就能搞出来. 首先看到这个问题,对于被d整除这个条件,很容易就想到是取余数为0,所以想到可能状态中刚开始含有取余数. 先说我的第一个想法,f[i][j]表示选取i个数且此时的mod为j,这样的思想是第一下蹦出来的,当时想的就是在线来搞最终的答案.不过转瞬即发现,这TM不就是暴力吗魂淡!并没有什么卵用,于是开始想这个状态可不可以做什么优化. 显然第二维的j并不需要太大的优化,暂且先将其搁置一边,来考虑第一维的i怎么优化. 把滚

COdeforces#417D Cunning Gena(状压DP)

A boy named Gena really wants to get to the "Russian Code Cup" finals, or at least get a t-shirt. But the offered problems are too complex, so he made an arrangement with his n friends that they will solve the problems for him. The participants