SGU132 Y

来源:互联网 发布:淘宝的华歌尔是正品吗 编辑:程序博客网 时间:2024/04/29 11:42

SGU132传送门

Bob really LOVES chocolate. He thinks he never gets enough. Imagine his joy when his parents told him that they would buy him many rectangular chocolate pieces for his birthday. A piece of chocolate is a2x1 or 1x2 rectangle. Bob's parents also bought him a nice birthday cake, which can be imagined as a matrix havingM rows andN columns. Some positions on the cake are occupied by candles, the others are empty. Bob's parents asked their son to place as many chocolate pieces as he can on the empty squares on the cake, in such a manner that no two chocolate pieces overlap. However, he would like to keep the chocolate pieces to himself. That's why, he wants to place only a minimal amount of them on the cake and keep the rest. In order not to make Mon and Dad suspicious, Bob wants to place the chocolate pieces in such a way, that no other piece may be placed on the cake (that is, there won't exist any two adjacent empty squares). Find the minimal number of pieces which need to be placed on the cake, so that they do not overlap and no extra piece may be added.

Input

The first line of the input contains 2 integers:M (1<=M<=70) andN (1<=N<=7). Next,M lines will follow, each of them containingN characters, describing the cake. The character on rowiand column j of the cake may be either a '*'(ASCII code 42), representing a candle, or a '.'(ASCII code46), representing an empty square.

Output

You should output one integer: the minimal amount of pieces of chocolate which need to be placed on the cake.

Sample Input

5 5.*..**......**.**.*..**..

Sample Output

4

题意:在一个N*M的矩阵中,有些位置不能放入巧克力,要求你放入尽可能少的1*2的巧克力,使得该矩阵中不能再放入巧克力.

分析:由于本题中间存在空的,所以用二维的dp表示状态不足。而每一层铺1*2方块会影响到上一层和下一层,用三维数组表示

dp[i][j][k]表示当前为第i层,已经铺好啦第i-1层,将要铺第i层,由于只能用1表示已铺,0,表示空,(不能像之前01表示竖着的1*2)

用dfs在铺i层时,i+1层也会被铺。因题目只给啦4M内存,要用滚动数组。

ACcode

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>using namespace std;const int INF=0x3f3f3f3f;int dp[2][1<<7][1<<7],tem1,tem2,n,m,t,a[77];void dfs(int i,int s1,int s2,int s,int num,int x){    if(i>0&&!(s1&(1<<i-1))&&!(s2&1<<i-1))return ; //表示当前层与上一层出现啦连续两个空格   if(i>1&&!(s2&(1<<i-1))&&!(s2&(1<<i-2)))return; //表示当前层出现啦连续两个空格    if(i>=m)    {        int &res=dp[x^1][s2][s];        res=min(res,dp[x][tem1][tem2]+num);        return ;    }    dfs(i+1,s1,s2,s,num,x);                            //不铺    if(i<m-1&&!(s2&(1<<i))&&!(s2&(1<<(i+1))))          //铺横着放的1*2        dfs(i+2,s1,s2|(1<<i)|(1<<(i+1)),s,num+1,x);    if(!(s2&(1<<i))&&!(s&(1<<i)))                      //铺竖着放的1*2        dfs(i+1,s1,s2|(1<<i),s|(1<<i),num+1,x);}char s[9];int main(){    scanf("%d%d",&n,&m);    {        memset(a,0,sizeof(a));        t=1<<m;        a[0]=t-1;        for(int i=1;i<=n;i++)        {            scanf(" %s",s);            for(int j=0;j<m;j++)            {                if(s[j]=='*')                {                    a[i]|=(1<<j);                }            }        }        a[n+1]=t-1;        memset(dp,0x3f,sizeof(dp));        dp[0][t-1][a[1]]=0;        int x=0;        for(int i=0;i<n;i++)        {            memset(dp[x^1],0x3f,sizeof(dp[x^1]));            for(int s1=0;s1<t;s1++)            {                for(int s2=0;s2<t;s2++)                {                    if(dp[x][s1][s2]==INF)continue;                    //cout<<dp[i][s1][s2]<<endl;                    tem1=s1,tem2=s2;                    dfs(0,s1,s2,a[i+2],0,x);                }            }            x^=1;        }        int ans=INF;        for(int i=0;i<t;i++)            ans=min(ans,dp[x][i][t-1]);        printf("%d",ans);    }    return 0;}

LightOJ - 1270传送门


There is an M x N board, six types of tiles are available, and each of them is infinitely many, you have to find the number of ways you can fill the board using the tiles. Two board configurations are different if at least in one cell, their colors differ. The tiles are given below:

                    

You cannot rotate or flip any tile. And no cell in the board should be empty. But some cells may be broken; you can't place any part of a tile in the broken cells. And there will be at least one cell which is not broken. The tiles shouldn't overlap.

For example, a 2 x 3 board can be colored by 5 ways, they are:

                


Input

Input starts with an integer T (≤ 100), denoting the number of test cases.

Each case starts with a line containing two integers: M N (1 ≤ M, N ≤ 100, min(M, N) ≤ 8). Each of the nextM lines contains N characters forming the board. There are two types of characters. A'.' means the cell is not broken; a '#' means the cell isbroken.

Output

For each case, print the case number and the number of ways the board can be colored. The number may be large, so, output the number modulo264.

Sample Input

3

2 3

...

...

2 3

..#

...

5 5

.....

.....

.....

.....

.....

Sample Output

Case 1: 5

Case 2: 2

Case 3: 21272

题意:给定区域,用六种木快去填充,问方案数。

分析:轮廓线DP用1表示已填充,0表示未填充,每填满一行会对下一行产生影响,用dfs求解填充满这一行时,下一行状态。

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>using namespace std;typedef unsigned long long LL;const int INF=0x3f3f3f3f;LL dp[111][1<<8];int a[111],n,m,tem1,tem2,flag,g[111][12],t;void dfs(int i,int s2,int s,int cut){    if(i>=m)    {        dp[cut+1][s]+=dp[cut][tem2];        return ;    }    if(s2&(1<<i))    {        dfs(i+1,s2,s,cut);//已填,时向后推一位    }    else    {    if(!(s&(1<<i)))                             //六种方块的填充条件        dfs(i+1,s2|(1<<i),s|(1<<i),cut);      if(i<m-1&&!(s2&(1<<i+1)))        dfs(i+2,s2|(1<<i)|(1<<i+1),s,cut);    if(i<m-1&&!(s&(1<<i))&&!(s&(1<<i+1)))        dfs(i+1,s2|(1<<i),s|(1<<i)|(1<<i+1),cut);    if(i<m-1&&!(s2&(1<<i))&&!(s2&(1<<i+1))&&!(s&(1<<i)))        dfs(i+2,s2|(1<<i)|(1<<i+1),s|(1<<i),cut);    if(i>0&&!(s&(1<<i))&&!(s&(1<<i-1)))        dfs(i+1,s2|(1<<i),s|(1<<i)|(1<<i-1),cut);    if(i<m-1&&!(s2&(1<<i+1))&&!(s&(1<<i+1)))        dfs(i+2,s2|(1<<i)|(1<<i+1),s|(1<<i+1),cut);    }}char s[111];int main(){    int tA,cas=0;    scanf("%d",&tA);    while(tA--)    {        scanf("%d%d",&n,&m);        flag=0;        memset(g,0,sizeof(g));        if(n>=m)            flag=1;        for(int i=0;i<n;i++)        {            scanf(" %s",s);            for(int j=0;j<m;j++)            {                if(s[j]=='#')                {if(flag)                    g[i][j]=1;                 else                    g[j][i]=1;                }            }        }        if(!flag)swap(n,m);        t=1<<m;        memset(a,0,sizeof(a));        a[0]=t-1;        a[n+1]=t-1;        for(int i=0;i<n;i++)        {            for(int j=0;j<m;j++)            {                if(g[i][j])                    a[i+1]|=(1<<j);            }        }        memset(dp,0,sizeof(dp));        dp[0][a[1]]=1;        for(int i=0;i<n;i++)        {                for(int s2=0;s2<t;s2++)                {                    if(!dp[i][s2])continue;                    tem2=s2;                    dfs(0,s2,a[i+2],i);                }        }        LL ans=dp[n][t-1];        printf("Case %d: %llu\n",++cas,ans);    }    return 0;}


原创粉丝点击