如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
思路:一开始准备建图跑dfs,但是那样的话,就会少很多种情况,例如2 5 6 7 10这样的情况。就只能每层dfs的时候,都要对已经走过的格子,进行扩展。当已经走过5个格子的时候,将走过的格子数改成字符串,放到set中,最终set里面字符串的个数就是答案数。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int maxx=1e5+100;
int vis[3][4],b[5][5];
int tol;
int d[4][2]={{-1,0},{1,0},{0,1},{0,-1}};
int a[10];
set<string> s;
inline string fcs()
{
string ans="";
string tt;
for(int i=0;i<5;i++)
{
int x=a[i];tt="";
if(x==0) tt="0";
while(x)
{
tt=tt+(char)('0'+x%10);
x/=10;
}
reverse(tt.begin(),tt.end());
ans=ans+tt+" ";
}
//cout<<ans<<endl;
return ans;
}
inline void dfs(int cnt)
{
if(cnt==5)
{
int tmp=0;
for(int i=0;i<3;i++)
{
for(int j=0;j<4;j++)
{
if(vis[i][j]) a[tmp++]=b[i][j];
}
}
//cout<<tmp<<endl;
s.insert(fcs());
return ;
}
for(int i=0;i<3;i++)
{
for(int j=0;j<4;j++)
{
if(vis[i][j])
{
for(int k=0;k<4;k++)
{
int x=d[k][0]+i;
int y=d[k][1]+j;
if(x<0 || x>=3 || y<0 || y>=4)continue;
if(!vis[x][y])
{
vis[x][y]=1;
dfs(cnt+1);
vis[x][y]=0;
}
}
}
}
}
}
int main()
{
tol=0;
memset(vis,0,sizeof(vis));
int num=0;
for(int i=0;i<3;i++) for(int j=0;j<4;j++) b[i][j]=++num;
for(int i=0;i<3;i++){
for(int j=0;j<4;j++){
vis[i][j]=1;
dfs(1);
vis[i][j]=0;
}
}
printf("%d\n",s.size());
return 0;
}
努力加油a啊