第七届蓝桥杯省赛7:剪邮票

剪邮票

如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。

请你计算,一共有多少种不同的剪取方法。

请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

          图1.jpg

          图2.jpg

          图3.jpg                                               

思路:从12各种随意抽5个,判断是否连通

#include<cstdio>
#include<cstring>
using namespace std;
int a[3][4]={
    {0,1,2,3},
    {4,5,6,7},
    {8,9,10,11}};//为了方便,均执行-1操作
int vec[15];
int res;
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
int vis[5][5];
bool Include(int x)
{
    for(int i=0;i<5;i++)
        if(vec[i]==x)    return true;
    return false;
}
void Connect(int y,int x)
{
    for(int i=0;i<4;i++)
    {
        int ny=dy[i]+y;
        int nx=dx[i]+x;
        if(0<=ny&&ny<3&&0<=nx&&nx<4&&!vis[ny][nx]&&Include(a[ny][nx]))
        {
                vis[ny][nx]=1;
                Connect(ny,nx);
        }
    }
}
void dfs(int i,int j)
{
    if(i==12)
    {
        if(j==5)
        {
            memset(vis,0,sizeof(vis));
            int y=vec[0]/4,x=vec[0]%4;
            vis[y][x]=1;
            Connect(y,x);
            int mark=0;
            for(int k=0;k<j;k++)
            {
                y=vec[k]/4;
                x=vec[k]%4;
                if(vis[y][x]==1)        
                    mark++;
            }
            if(mark==5)    res++;
        }
        return ;
    }
    vec[j]=*(a[0]+i);
    dfs(i+1,j+1);
    vec[j]=0;
    dfs(i+1,j);
}

int main()
{
    res=0;
    dfs(0,0);
    printf("%d
",res);
    return 0;
}
/*
res:116
*/
原文地址:https://www.cnblogs.com/program-ccc/p/5321243.html