2016蓝桥杯C/C++省赛 剪邮票(深搜DFS+暴力)

来源:互联网 发布:淘宝联盟怎么一起结算 编辑:程序博客网 时间:2024/06/06 04:34

题目:


思路:

先枚举一下组合数,也就是C(12,5)=792种可能,然后判断每一种可能是否连通,那怎么判连通呢?因为我的num[1]~num[5]存储的是那五个数,所以我们判断如果从num[1]能走到num[2]~num[5]中的任意一个点的话,就证明这一片区域是连通的,用一个flag变量来记录从num[1]走到其他点成功的次数,总共有四种可能(1~2,1~3,1~4,1~5),如果都能走到的话,那么flag的值应该是4,这样的话就证明连通一个去区域了,所以就把cntt++,最后输出cntt的值就行,(x1,y1)代表的是起始点的坐标,(x2,y2)代表终点的坐标,注意实时更新,感觉时间复杂度有点高,但是才跑了0.033s...

代码:

#include <stdio.h>#include <string.h>#include <string>#include <iostream>#include <stack>#include <queue>#include <vector>#include <algorithm>#define mem(a,b) memset(a,b,sizeof(a))#define inf 0x3f3f3f3f#define N 1000+10#define LL long longusing namespace std;int num[10],cntt=0,flag;int vis[10][10];int go[4][2]={1,0,-1,0,0,1,0,-1};int x2,y2;int judge(int x,int y)//判断这个点是否在这五个点内{    int k=4*(x-1)+y;//坐标转换成数字    for(int i=1;i<=5;i++)    {        if(k==num[i])            return 1;    }    return 0;}void dfs(int x1,int y1){    if(x1==x2&&y1==y2)    {        flag++;        return;    }    for(int i=0; i<4; i++)    {        int xx=x1+go[i][0];        int yy=y1+go[i][1];        if(xx>=1&&xx<=3&&yy>=1&&yy<=4&&vis[xx][yy]==0&&judge(xx,yy))        {            vis[xx][yy]=1;            dfs(xx,yy);        }    }}void init(int nn,int mm){    int i;    if(mm==0)//当mm==0时,num[1]~num[5]中存储的就是枚举的这五个数    {        flag=0;//初始化flag        int x1=(num[1]-1)/4+1;//把数值num[1]转换成坐标的形式        int y1=(num[1]-1)%4+1;        for(int i=2; i<=5; i++)//搜索从num[1]分别走到num[2]~num[5],如果都可以走到的话,证明这一片区域是连通的        {            x2=(num[i]-1)/4+1;//转换成坐标            y2=(num[i]-1)%4+1;            mem(vis,0);//标记数组清零            vis[x1][y1]=1;//标记当前点            dfs(x1,y1);//从起点开始搜索        }        if(flag==4)//一共有四种可能,如果都能走得通,就证明这一片区域连通            cntt++;        return;    }    for(int i=nn; i>=mm; i--)//枚举组合数    {        num[mm]=i;        init(i-1,mm-1);    }}int main(){    init(12,5);//枚举组合数,在12个数中选5个数的组合    cout<<cntt<<endl;}



0 0
原创粉丝点击