剪郵票
如【圖1.jpg】, 有12張連在一起的12生肖的郵票。
現在你要從中剪下5張來,要求必須是連着的。
(僅僅連接一個角不算相連)
比如,【圖2.jpg】,【圖3.jpg】中,粉紅色所示部分就是合格的剪取。
請你計算,一共有多少種不同的剪取方法。
思路:
沒錯,一開始我傻到寫了個暴搜,天真的以爲每個重複了五次,除以5即可...mmp,後來纔想起來....
因爲每個位置每次所走的方向不一樣也會導致同一個解,這就導致每一個重複次數不確定,所以GG。
因爲只需找五個,而且還是填空題,我們可以五層for找到五個點(當然暴搜好像更方便代碼更簡潔啊),BFS判斷一下五個點是否聯通即可(這裏因爲想找到所有情況一下子判斷有點難,乾脆搜索吧)
最後答案116
#include <bits/stdc++.h>
using namespace std;
int a[10];
int Go[4][2] = {0,1,1,0,0,-1,-1,0};
bool check()
{
int book[30];
memset(book,0,sizeof book);
for(int i = 1;i <= 5;++i)
book[a[i]] = 1;
queue<int>Q;
while(!Q.empty()) Q.pop();
bool vis[30];
memset(vis,0,sizeof vis);
vis[a[1]] = 1;
Q.push(a[1]);
while(!Q.empty())
{
int cur = Q.front();Q.pop();
int x = (cur-1) /4;int y = (cur - 1)% 4;
for(int i = 0;i < 4;++i)
{
int tx = x + Go[i][0];
int ty = y + Go[i][1];
int nxt = tx * 4 + ty + 1;
if(tx >= 0 && tx < 3 && ty >= 0 && ty < 4 && !vis[nxt] && book[nxt])
{
vis[nxt] = 1;
Q.push(nxt);
}
}
}
for(int i = 1;i <= 5;++i)
if(vis[a[i]] == 0)
return 0;
return 1;
}
int main()
{
int ans = 0;
for(int i = 1;i <= 12;++i)
{
a[1] = i;
for(int j = i + 1;j <= 12;++j)
{
a[2] = j;
for(int k = j + 1;k <= 12;++k)
{
a[3] = k;
for(int l = k + 1;l <= 12;++l)
{
a[4] = l;
for(int g = l + 1;g <= 12;++g)
{
a[5] = g;
if(check())
ans++;
}
}
}
}
}
printf("%d\n",ans);
return 0;
}