這道題不知道爲啥當時就是沒有做出來,自習回顧了一遍一看就是個搜索,但是敲了一邊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;
}