只能說比賽時前期做得太慢了,後面導致題目只能撈點分數(IOI賽制),當時這道題是我不剪枝DFS拿了4分,壓線拿銅牌!
考完試一做,發現是個大水題(bushi)
主要原理:DFS(深度優先搜尋) + 剪枝
名言:學搜尋核心就是學剪枝
廢話不說了,見程式碼
點選檢視程式碼
//原理:DFS + 剪枝
#include <bits/stdc++.h>
using namespace std;
int k,n;//k為要求的行列和,n為方格大小
int row[5];//row為已經填好數的某行的和
int col[5];//col同理
//神之一筆:剪枝.(1)如果n-1定了,最後一個不用管了,一定為k - row[x](列同理).(2)列舉可填數的時候可以限定範圍,維護行列和不超過k
int ans;//記錄答案
void DFS(int x,int y)//核心DFS
{
if(y > n-1)//如果要換行了
{
x++;//換行
y = 1;//重置y
}
if(x == n)//如果到了底行,進行特判(之前的行列和(左上角的n-1矩陣)滿足<=k,但是不能保證最後的行列和<=k,故要特判)
{
//其實由數學推算:最後右下角的代表數是一致的,故sumr與sumc一個就夠了,沒觀察出也沒關係,兩個不影響
int sumr = 0,sumc = 0;//初始化為0
for (int i = 1;i<=n-1;i++) sumc += (k - row[i]);//累加之前行
for (int i = 1;i<=n-1;i++) sumr += (k - col[i]);//累加之前列
if(sumc <= k&&sumr <= k) ans++;//如果<=k,答案合法,+1
return;//切記,一定要返回
}
for (int i = 0;i<=k-row[x]&&i<=k-col[y];i++)//限制性列舉,維護左上角矩陣行列和<=k,記住從0開始
{
row[x] += i;//累加行
col[y] += i;//累加列
DFS(x,y+1);//遞迴搜尋
row[x] -= i;//刪去
col[y] -= i;//刪去
}
}
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>k>>n;//輸入
DFS(1,1);//搜尋
cout<<ans<<"\n";//輸出
return 0;
}