NOIP2016模擬 遊戲 搜索

這裏寫圖片描述
來源:重慶一中


這道題其實顯然是搜索,只不過我看到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);
}
發佈了105 篇原創文章 · 獲贊 23 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章