ACdream 1132 Chess

Chess

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

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.

Source

dut200901102

Manager



狀態壓縮DP,許久沒有碰狀態壓縮DP,這次一作果然生疏不少,這題一看到一想蠻簡單的上一層可以直接轉移狀態到下一層,結果沒有考慮周全,胡亂WA了兩次都不知道錯在哪,靜下心來仔細分析後才發現並不是可以直接推的,我少考慮了一個狀態,比如0010是可以推到1000的,因爲我開始做的時候除了兩邊的層之外要保證前一層滿佔據,1000雖然沒有保證0010滿佔據,但其實更上一層的情況是可以左右0010的佔據情況的,本以爲這樣三層DP會不會TLE,但再次分析之後發現許多情況重複,可以先預處理加判斷少好幾層的DP,所以是可行的,但是枚舉的不是三層的情況,而是上一層和這一層和上上一層對上一層的加成可能情況(真是彆扭~~)

看代碼知道更多

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<cmath>
#define rep(i,n) for(i=1;i<=n;i++)
#define MM(a,t) memset(a,t,sizeof(a))
#define INF 1e9
typedef long long ll;
#define mod 1000000007
using namespace std;
int n,m;
int ken[11][11];
int dp1[11][514][514];
int ptwo[10],sum[514],ko[514];
int hefa[514],fhefa[11][514];
int jicot(int num){
    int i,j,res=0;
    while(num>0){
      res+=num&1;
      num>>=1;   
    }
    return res;
}
int jiko(int num){
	int i,j,res=0;
	int wei[11];
	MM(wei,0);
    i=n;
    while(i>0){
    	if((num&1)==1){
	    	wei[i]=1; wei[i+1]=1; wei[i-1]=1;
	    }
    	num>>=1;
    	i--;
    	if(num==0) break;
    }
    for(i=n;i>=1;i--){
    	if(wei[i]==1) res+=ptwo[n-i];
    }
    return res;
}
bool check(int num,int ii){
    int i=n,j;
    while(i>0){
        if(ken[ii][i]==1 && (num&1)==1) return false;
        i--;
        num>>=1;
        if(num==0) return true;
    }
    return true;
}
void dpmain(){
    int i,pr,now,prr;
     
    for(now=0;now<ptwo[n];now++)
    if(fhefa[1][now]) { dp1[1][now][ko[now]]=sum[now];  }
	for(i=2;i<=n;i++)
      for(pr=0;pr<ptwo[n];pr++)
       if(fhefa[i-1][pr])
        for(now=0;now<ptwo[n];now++)
        if((pr & now)==0 && fhefa[i][now])
	    {
			if(i==n && (ko[now]|pr)!=ptwo[n]-1) continue; 
			for(prr=pr;prr<ptwo[n];prr++) {
  	          if(dp1[i-1][pr][prr]==-1 || (now|prr)!=ptwo[n]-1) continue;   	
              dp1[i][now][ko[now]|pr]=(dp1[i][now][ko[now]|pr]==-1)?dp1[i-1][pr][prr]+sum[now]:min(dp1[i][now][ko[now]|pr],dp1[i-1][pr][prr]+sum[now]);	
			}   
		}       

  
}
int jihefa(int num){
    int i=9,j;
    while(i>0){
        if((num&2)==2 && (num&1)==1) return 0;
        i--;
        num>>=1;
        if(num==0) return 1;
    }
    return 1;
}
void setup(){
	int i,j;
	
    ptwo[0]=1;
    rep(i,9){
         ptwo[i]=ptwo[i-1]*2;
    }
    for(i=0;i<ptwo[9];i++){ 
	  sum[i]=jicot(i);
      hefa[i]=jihefa(i);
	}
}
int main()
{
    int i,j;
     
    setup();
    while(scanf("%d%d",&n,&m)!=EOF){
        MM(ken,0); MM(dp1,-1);
        rep(i,m){
            int x,y;
            scanf("%d%d",&x,&y);
            ken[x][y]=1;
        }
        for(i=0;i<ptwo[n];i++)
          ko[i]=jiko(i);
        MM(fhefa,0);
        rep(i,n)
          for(j=0;j<ptwo[n];j++)
           if(hefa[j] && check(j,i)) fhefa[i][j]=1;
        if(n==1){
            if(ken[1][1]==1) printf("-1\n");
            else             printf("1\n");
            continue;
        }
        dpmain();
        int res=1000;
        for(i=0;i<ptwo[n];i++)
        if(dp1[n][i][ptwo[n]-1]!=-1){
            res=min(res,dp1[n][i][ptwo[n]-1]);
        }
        if(res==1000) printf("-1\n"); 
        else          printf("%d\n",res);
    }
     
    return 0;
}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章