题意:

给你一个w*h的区域,给你n个不同的地毯,告诉你每个地毯的长宽,让你把区域铺满,地毯可以旋转,不能重叠,不能剪小。问你能不能铺满。其中1≤wi≤100;1≤hi≤100;1≤n≤7。

思路:

这属于小规模的平铺类搜索。

平铺:不允许重叠,将给出的一些方块(最容易处理的是长方形了)放置在一个目标区域内。

小规模:要放置的方块数量<10,放置的目标区域的边长<=100。

贪心策略是找到带有空闲单元格的最顶行,然后选择最左边的单元格。

然后搜一下就可以了。

我太菜了这种DFS不会写QAQ

然后学习了一下标程再写的QAQ

当然还有一种方法是全排列一下,根据顺序来放。

还是讲一下这深搜是怎么写的吧(每次写这种DFS就无从下手的感觉

先确定两个参数,x,y表示当前开始铺的位置。

枚举地毯,这里旋转用了swap,可以让代码简洁一点,如果这个地毯没有被用过,就验证一下能不能放(放了以后越界而且覆盖的地方之前都没有被铺过)。

如果可以放,就放进去,递归调用dfs(x+a,y),因为要尽量从最左上放,所以y不动,x+a,如果后面这样放是可以的就返回true,不行的话回溯,把标记还原。

还要注意dfs里边界条件,如果x为w的话就铺下一行,如果y为h就返回true,如果这个单元格被铺过了的话就铺左边一个。

写DFS的时候就心里觉得调起来肯定很麻烦就不敢写,这样不行,写之前细节都想想好,会好一点。

代码:

int w,h,c;
bool mp[110][110];
struct node
{
    int a,b,cnt;
}carp[10];
bool dfs(int x,int y)
{
    //printf("%d,%d\n",x,y);
    if(x==w){/*printf("!\n");*/return dfs(0,y+1);}
    if(y==h){/*printf("?\n");*/return true;}
    if(mp[x][y]){/*printf(".\n");*/return dfs(x+1,y);}
    for(int i=0;i<c;i++)
    {
        if(carp[i].cnt>0)
        {
            int cura=carp[i].a,curb=carp[i].b;
            for(int j=0;j<2;j++)
            {
                swap(cura,curb);
                if(x+cura>w)continue;
                if(y+curb>h)continue;
                int sign=0;
                for(int k=0;k<cura&&sign==0;k++)
                {
                    for(int l=0;l<curb&&sign==0;l++)
                    {
                        int curx=x+k,cury=y+l;
                        if(mp[curx][cury])sign++;
                    }
                }
                if(sign!=0)continue;
                carp[i].cnt--;
                for(int k=0;k<cura;k++)
                    for(int l=0;l<curb;l++)
                    {
                        int curx=x+k,cury=y+l;
                        mp[curx][cury]=true;
                    }
                if(dfs(x+cura,y))return true;
                carp[i].cnt++;
                for(int k=0;k<cura;k++)
                    for(int l=0;l<curb;l++)
                    {
                        int curx=x+k,cury=y+l;
                        mp[curx][cury]=false;
                    }
                if(cura==curb)break;
            }
        }
    }
    return false;
}
int main()
{
    scanf("%d%d",&w,&h);
    scanf("%d",&c);
    memset(mp,0,sizeof(mp));
    for(int i=0;i<c;i++)
       scanf("%d%d%d",&carp[i].cnt,&carp[i].a,&carp[i].b);
    if(dfs(0,0))printf("yes\n");
    else printf("no\n");
    return 0;
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

LOJ515 & 51nod1573 Bitset乱搞 Previous
旅行商问题 Next