2019 藍橋杯省賽 B 組模擬賽(一)——馬的管轄(狀態壓縮)

題目鏈接:https://www.jisuanke.com/contest/9082?view=challenges

 這道題不知道爲啥當時就是沒有做出來,自習回顧了一遍一看就是個搜索,但是敲了一邊dfs,發現跑了十好幾分鐘還沒跑完。於是打消了dfs想法,轉化成狀態壓縮枚舉5*5的棋盤的00..000到11...11的狀態(都是25個)。判斷每個狀態是否符合題目中的全覆蓋概念,如果符合就可以統計相應狀態的方案數。

 雖然此程序複雜度也很高,需要跑13秒左右,但是對於填空題,並且相對於dfs來說,這至少是個可行的方法。

#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
#include <cstdio>
#include <string>
#include <stack>
#include <set>
#define IOS ios::sync_with_stdio(false), cin.tie(0)
using namespace std;
typedef long long ll;
ll ans[26];//ans[cnt]表示合法方案下馬的個數是cnt個的方案個數
bool mp[6][6];//mp[i][j]=true;表示(i,j)放了一個馬
ll minn=30;//記錄最優方案的馬的數量
int next_s[8][2]={-2,1,-1,2,1,2,2,1,2,-1,1,-2,-1,-2,-2,-1};
ll n;
//判斷當前狀態是否合法
bool judge() {
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if (mp[i][j])continue;//該位置有馬,自然被覆蓋
			bool flag = false;//沒有馬,判斷和他有關的8個位置是否有馬將它覆蓋
			for (int k = 0; k < 8; k++) {
				ll tx = i + next_s[k][0];
				ll ty = j + next_s[k][1];
				if (tx >= 0 && tx < n && ty >= 0 && ty < n && mp[tx][ty]) {
					//判斷蹩馬腿的情況
                    if (abs(tx - i) == 2) {
						if (!mp[(tx + i)/2][ty]) {
							flag = true; break;
						}
					}
					else {
						if (!mp[tx][(ty + j) / 2]) {
							flag = true;
							break;
						}
					}
				}
			}
			if (!flag)return false;
		}
	}
	return true;
}
int main()
{
    IOS;
    n=5;
    for(ll i=0;i<(1<<25);i++){//枚舉狀態
        ll cnt=0;//統計馬的數量
        memset(mp,false,sizeof(mp));
        for(int k=0;k<25;k++){
            mp[k/5][k%5]=((i>>k)&1)==1?true:false;
            if((i>>k)&1)cnt++;
        }
        //判斷該狀態是否合法
        if(judge()){
            minn=min(minn,cnt);
            ans[cnt]++;
        }
    }
    //cout<<minn<<endl;
    cout<<ans[minn]<<endl;//
    getchar();
    getchar();
    return 0;
}

 

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