蓝桥杯——剪邮票

如【图1.jpg】, 有12张连在一起的12生肖的邮票。

现在你要从中剪下5张来,要求必须是连着的。

(仅仅连接一个角不算相连) 比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。

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

【最终结果】

116

思路

1.首先从12个数里面取出5个数来

2.把这五个数保存在mpt[3][4]当中,是这五个数的位置用1表示,不是的用0表示

3.判断这五个数是否相连

4.用深度遍历的方法判断。

#include <iostream>
#include <string>
using namespace std;

int sum = 0;

int a[12] = {1,2,3,4,5,6,7,8,9,10,11,12};
int mpt[3][4]; 
int mpt_cmd[3][4];
int b[5];//保存取出来的五个元素
int count = 0;
int mect[4][2] = {1,0,-1,0,0,1,0,-1};

void Print()
{
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<4;j++)
        {
            cout<<mpt[i][j]<<" ";
        }
        cout<<endl;
    }
    
    cout<<endl;
    cout<<endl;
}

int Hand(int x,int y)//判断mpt[x][y],是否在mpt_cmd中,在里面返回0,不在返回1;
{
    if(mpt[x][y] == mpt_cmd[x][y])
    {
        return 0;
    }
    return 1;
    
}

void Lianjie(int x,int y)//判断五个数是否连接
{
    int x1,y1;
    for(int i=0;i<4;i++)//有四个方向
    {
        x1 = x+mect[i][0];
        y1 = y+mect[i][1];
        if(x1<0||x1>=3||y1<0||y1>=4)//超出界限了
            continue;
        if((mpt[x1][y1] == 0)|| (Hand(x1,y1) == 0))//该点不是所抽的五个数,或者该点已经遍历过
            continue;
        mpt_cmd[x1][y1] = 1;
        count++;
        Lianjie(x1,y1);            
    }
}

void Add()//抽取的五个数
{
    count = 0;
    memset(mpt,0,sizeof(mpt));//把数组初始化为0;
    memset(mpt_cmd,0,sizeof(mpt_cmd));
    int x,y;
    for(int i=0;i<5;i++)//将抽出来的五个数保存到数组mpt中,另该出为1,其它处为零
    {
         
        x = (b[i]-1)/4;
        y = (b[i]-1)%4;
        mpt[x][y] = 1;
    }

    
    count =1;
    Lianjie(x,y);//从保存的最后一个数当起点
    if(count==6)
    {
        //Print();输出每一种情况
        sum++;
    }
}



void fun(int m,int n)
{
    int i;
    for(i=m;i>=n;i--)
    {
        b[n-1] = a[i-1];
        if(n>1)
            fun(i-1,n-1);
        else
        {
            Add();
        }
    }
    
}

int main()
{
    fun(12,5);
    cout<<sum++<<endl;
    return 0;
}

 

public class Main
{
    static int art[][]    = new int[3][4];
    static int brt[] = {1,2,3,4,5,6,7,8,9,10,11,12};//12个数
    static int qv[] = new int[5];//取5个数
    static int fx[][] = {{0,1},{0,-1},{1,0},{-1,0}};
    
    static int count =0;
    static int sum = 0;//保存所有的结果

    public static void print()
    {
        for(int i=0;i<3;i++)
        {
            for(int j=0;j<4;j++)
            {
                System.out.print(art[i][j]);
            }
            System.out.println();
        }
    }
    
    public static void print1()
    {
        for(int i:qv)
        {
            System.out.print(i+" ");
        }
        System.out.println();
    }
    
    public static void dfs(int x,int y,int art1[][],boolean vis[][])
    {
        if(x<0||x>=3||y<0||y>=4||vis[x][y]||art1[x][y]!=1)//越界或者被标记,或者不是1
            return;
        count++;
        vis[x][y] =true;
        for(int i=0;i<4;i++)
        {
            dfs(x+fx[i][0], y+fx[i][1],art1,vis);
        }
    }
    
    public static boolean f()//判断五张邮票是否在一起
    {
        int art1[][] = new int[3][4];
        boolean vis[][] = new boolean[3][4];
        for(int i=0;i<=11;i++)//把数组都标记为0
        {
            art1[i/4][i%4] = 0;
        }
        for(int i=0;i<5;i++)//把取出来的五个数标记为1
        {
            art1[(qv[i]-1)/4][(qv[i]-1)%4]=1;
        }
        count =0;
        dfs((qv[0]-1)/4, (qv[0]-1)%4, art1,vis);
        if(count == 5)
        {
            return true;//有五个相连
        }
        return false;//没有五个相连
    }
    
    
    public static void fun(int n,int i)
    {
        if(i==12 || n>=5)
        {
            if(n==5  && f())//判断这五张邮票是否连在一起
            //if(n==5)
            {
                //print1();//所有满足的情况
                sum++;
            }
            return;
        }
        
        qv[n] =brt[i];
        fun(n+1, i+1);//第i个数取
        
        fun(n, i+1);//第i个数不取
        
        
    }
    
    
    
    public static void main(String[] args)
    {
        for(int i=0;i<=11;i++)
        {
            art[i/4][i%4] = i+1;
        }
        
        fun(0,0);
        System.out.println(sum);
        
    }

}

 

posted @ 2019-03-16 13:42  池塘之底  阅读(246)  评论(0编辑  收藏  举报