NOIP2016模拟 游戏 搜索

来源:互联网 发布:js怎么设置按钮被点击 编辑:程序博客网 时间:2024/05/17 10:06

这里写图片描述
来源:重庆一中


这道题其实显然是搜索,只不过我看到20*20的数据范围觉得搜索不稳,乱想了比较久,最后只交了个非常暴力的搜索,而且爆零了。搜索是弱项,还需好好加强。

20*20,理论上来说有2400种可能,那么要想搜得好,就看怎么剪枝了。数据范围这么大,怎样剪枝比较好呢?事实上并不需要多好的剪枝。题目中说“保证只有唯一解”,那么说明仅仅按这个游戏的规则进行剪枝就能剪掉很多。既然答案唯一,那么搜到了一个答案就不搜了。

所以其实是跑得飞快的。

#include<stdio.h>int M,N,Black,row[25][25],col[25][25],Tr[25],Tc[25];//Tr记录某一行的黑色块总数,Tc记录某一列的黑色块总数int Map[25][25];bool cr(int x,int r)//检查第x行0~r位置是否合法{    int i,tot=0,Now=1,tmp=0;    for(i=0;i<=r;i++)    {        if(Map[x][i])        {            tmp++;tot++;            if(tmp>row[x][Now])return false;        }        else if(tmp)        {            if(tmp!=row[x][Now])return false;            tmp=0;Now++;        }    }    if(tot+M-r-1<Tr[x])return false;//剩下的位置全部填满也不行,不合法    if(tot>Tr[x])return false;//多了,不合法    return true;}bool cc(int x,int r)//检查第x列0~r位置是否合法,基本上和cr函数一样{    int i,tot=0,Now=1,tmp=0;    for(i=0;i<=r;i++)    {        if(Map[i][x])        {            tmp++;tot++;            if(tmp>col[x][Now])return false;        }        else if(tmp)        {            if(tmp!=col[x][Now])return false;            tmp=0;Now++;        }    }    if(tot+N-r-1<Tc[x])return false;    if(tot>Tc[x])return false;    return true;}bool Find;void DFS(int cur,int rem)//cur:当前讨论到的格子的编号,从0开始;rem:剩下的黑色块的数量{    if(Find)return;    int i,x,y;    if(cur)    {        x=(cur-1)/M;y=(cur-1)%M;        if(!cr(x,y))return;        for(i=0;i<=y;i++)if(!cc(i,x))return;    }    if(cur==N*M)    {        int i,j;        for(i=0;i<N;i++,putchar('\n'))        for(j=0;j<M;j++)        {            if(Map[i][j])putchar('#'),putchar('#');            else putchar(' '),putchar(' ');        }        Find=true;        return;    }    if(rem==-1)return;    x=cur/M;y=cur%M;    Map[x][y]=1;    DFS(cur+1,rem-1);    Map[x][y]=0;    DFS(cur+1,rem);}int main(){    int i,x;    scanf("%d%d",&M,&N);    for(i=0;i<M;i++)    {        scanf("%d",&x);        while(x)        {            col[i][++col[i][0]]=x;Black+=x;Tc[i]+=x;            scanf("%d",&x);        }    }    for(i=0;i<N;i++)    {        scanf("%d",&x);        while(x)        {            row[i][++row[i][0]]=x;Tr[i]+=x;            scanf("%d",&x);        }    }    DFS(0,Black);}
原创粉丝点击