hdu5731(状压+容斥)

题意:多米诺骨牌的矩形完全覆盖,
           要求统计没有横切割线和竖切割线的方案数

题解

第一部分就是轮廓线 DP 的入门裸题
预处理出任意矩形大小的方案数 RES[i][j]
不过我怀疑这部分不提前打表的过不了

第二部分是一个容斥
先对列容斥,用状压的方式枚举出所有列的分割情况
然后计算,当前列分割情况下,行没有分割的方案数 dp[n]
然后再用容斥,奇加偶减即能得出答案

dp[n]   的求法为,设当前分割下,宽度为 x的无限制覆盖为 cnt[x]


cnt[x]=RES[x][bsiz1]RES[x][bsiz2]...RES[x][bsizt]


其中 bsiz1...bsizt 为列分割线分割出的每一块的横向大小


dp[i]=cnt[i]i1j=0dp[j]cnt[ij]

其中 cnt[i] 为宽度为 i的任意覆盖,
减去每一个前 j 个无行分割线,后 ij 个有行分割线的方案
减去这些互斥的非法方案,剩下的即为宽度为 i 的无行分割线的合法覆盖


大神的思想就是不一样,,,,,我是想不到。但是起码学到了容斥的  奇加偶减!!!!

Dominoes are rectangular tiles with nice 2 × 1 and 1 × 2 sizes.

The tiling is called solid if it is not possible to split the tiled rectangle by a straight line, not crossing the interior of any tile. For example, on the picture below the tilings (a) and (b) are solid, while the tilings (c) and (d) are not.



Now the managers of the company wonder, how many different solid tilings exist for an m × n rectangle. Help them to find that out.
 

Input
The input file contains m and n(1m,n16) .
 

Output
Output one integer number mod 1e9+7 - the number of solid tilings of m×n rectangle with 2 × 1 and 1 × 2 pavement tiles.
 

Sample Input
  
  
2 2 5 6 8 7
 

Sample Output
 
 
0 6 13514
Hint
All solid tilings for the 5×6 rectangle are provided on the picture below:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;

const int mod=1e9+7;
typedef long long ll;
int n,m;
//int dp[20][70000];
int ans[20][70000];
void init();
ll solve()
{
   int bcnt,bsize,block[20];
   int dp[20];
   int res=0;
   for(int i=0;i<1<<(m-1);i++)
   {
       bcnt=bsize=0;
       for(int j=0;j<m-1;j++)
       {
           if(i&(1<<j))
           {
               block[bcnt++]=++bsize;
               bsize=0;
           }
           else
                bsize++;
       }
       block[bcnt++]=++bsize;
       for(int j=1;j<=n;j++)
       {
           for(int k=0;k<j;k++)
           {
               ll cnt=1;
               for(int l=0;l<bcnt;l++)
               {
                    cnt=(cnt*ans[j-k][block[l]])%mod;
               }
               if(k==0)
                    dp[j]=cnt;
               else
                    dp[j]=(dp[j]-cnt*dp[k])%mod;
           }
       }
       if(bcnt&1)
        res=(res+dp[n])%mod;
       else
        res=(res-dp[n])%mod;
   }
   return ((res+mod)%mod);
}

int main()
{
    init();//未容斥前的铺砖总数
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        printf("%lld\n",solve());
    }
    return 0;
}

//void dfs(int i,int j,int state,int next,int n)
//{
//    if(j==n)
//    {
//        dp[i+1][next]+=dp[i][state];
//        dp[i+1][next]%=mod;
//        return;
//    }
//    if(((1<<j)&state)>0)
//        dfs(i,j+1,state,next,n);
//    if(((1<<j)&state)==0)
//        dfs(i,j+1,state,next|(1<<j),n);
//    if(j+1<n&&((1<<j)&state)==0&&(1<<(j+1)&state)==0)
//       dfs(i,j+2,state,next,n);
//}
//
//void solve(int n,int m)
//{
//    memset(dp,0,sizeof(dp));
//    dp[1][0]=1;
//    for(int i=1;i<=m;i++)
//        for(int j=0;j<(1<<n);j++)
//            if(dp[i][j])
//                dfs(i,0,j,0,n);
//    ans[n][m]=dp[m+1][0];
//}
//
//void init()
//{
//    for(int i=1;i<=16;i++)
//        for(int j=1;j<=16;j++)
//        {
//            solve(i,j);
//            printf("ans[%d][%d]=%d;\n",i,j,ans[i][j]);
//        }
//}

void init()
{
ans[1][1]=0;
ans[1][2]=1;
ans[1][3]=0;
ans[1][4]=1;
ans[1][5]=0;
ans[1][6]=1;
ans[1][7]=0;
ans[1][8]=1;
ans[1][9]=0;
ans[1][10]=1;
ans[1][11]=0;
ans[1][12]=1;
ans[1][13]=0;
ans[1][14]=1;
ans[1][15]=0;
ans[1][16]=1;
ans[2][1]=1;
ans[2][2]=2;
ans[2][3]=3;
ans[2][4]=5;
ans[2][5]=8;
ans[2][6]=13;
ans[2][7]=21;
ans[2][8]=34;
ans[2][9]=55;
ans[2][10]=89;
ans[2][11]=144;
ans[2][12]=233;
ans[2][13]=377;
ans[2][14]=610;
ans[2][15]=987;
ans[2][16]=1597;
ans[3][1]=0;
ans[3][2]=3;
ans[3][3]=0;
ans[3][4]=11;
ans[3][5]=0;
ans[3][6]=41;
ans[3][7]=0;
ans[3][8]=153;
ans[3][9]=0;
ans[3][10]=571;
ans[3][11]=0;
ans[3][12]=2131;
ans[3][13]=0;
ans[3][14]=7953;
ans[3][15]=0;
ans[3][16]=29681;
ans[4][1]=1;
ans[4][2]=5;
ans[4][3]=11;
ans[4][4]=36;
ans[4][5]=95;
ans[4][6]=281;
ans[4][7]=781;
ans[4][8]=2245;
ans[4][9]=6336;
ans[4][10]=18061;
ans[4][11]=51205;
ans[4][12]=145601;
ans[4][13]=413351;
ans[4][14]=1174500;
ans[4][15]=3335651;
ans[4][16]=9475901;
ans[5][1]=0;
ans[5][2]=8;
ans[5][3]=0;
ans[5][4]=95;
ans[5][5]=0;
ans[5][6]=1183;
ans[5][7]=0;
ans[5][8]=14824;
ans[5][9]=0;
ans[5][10]=185921;
ans[5][11]=0;
ans[5][12]=2332097;
ans[5][13]=0;
ans[5][14]=29253160;
ans[5][15]=0;
ans[5][16]=366944287;
ans[6][1]=1;
ans[6][2]=13;
ans[6][3]=41;
ans[6][4]=281;
ans[6][5]=1183;
ans[6][6]=6728;
ans[6][7]=31529;
ans[6][8]=167089;
ans[6][9]=817991;
ans[6][10]=4213133;
ans[6][11]=21001799;
ans[6][12]=106912793;
ans[6][13]=536948224;
ans[6][14]=720246619;
ans[6][15]=704300462;
ans[6][16]=289288426;
ans[7][1]=0;
ans[7][2]=21;
ans[7][3]=0;
ans[7][4]=781;
ans[7][5]=0;
ans[7][6]=31529;
ans[7][7]=0;
ans[7][8]=1292697;
ans[7][9]=0;
ans[7][10]=53175517;
ans[7][11]=0;
ans[7][12]=188978103;
ans[7][13]=0;
ans[7][14]=124166811;
ans[7][15]=0;
ans[7][16]=708175999;
ans[8][1]=1;
ans[8][2]=34;
ans[8][3]=153;
ans[8][4]=2245;
ans[8][5]=14824;
ans[8][6]=167089;
ans[8][7]=1292697;
ans[8][8]=12988816;
ans[8][9]=108435745;
ans[8][10]=31151234;
ans[8][11]=940739768;
ans[8][12]=741005255;
ans[8][13]=164248716;
ans[8][14]=498190405;
ans[8][15]=200052235;
ans[8][16]=282756494;
ans[9][1]=0;
ans[9][2]=55;
ans[9][3]=0;
ans[9][4]=6336;
ans[9][5]=0;
ans[9][6]=817991;
ans[9][7]=0;
ans[9][8]=108435745;
ans[9][9]=0;
ans[9][10]=479521663;
ans[9][11]=0;
ans[9][12]=528655152;
ans[9][13]=0;
ans[9][14]=764896039;
ans[9][15]=0;
ans[9][16]=416579196;
ans[10][1]=1;
ans[10][2]=89;
ans[10][3]=571;
ans[10][4]=18061;
ans[10][5]=185921;
ans[10][6]=4213133;
ans[10][7]=53175517;
ans[10][8]=31151234;
ans[10][9]=479521663;
ans[10][10]=584044562;
ans[10][11]=472546535;
ans[10][12]=732130620;
ans[10][13]=186229290;
ans[10][14]=274787842;
ans[10][15]=732073997;
ans[10][16]=320338127;
ans[11][1]=0;
ans[11][2]=144;
ans[11][3]=0;
ans[11][4]=51205;
ans[11][5]=0;
ans[11][6]=21001799;
ans[11][7]=0;
ans[11][8]=940739768;
ans[11][9]=0;
ans[11][10]=472546535;
ans[11][11]=0;
ans[11][12]=177126748;
ans[11][13]=0;
ans[11][14]=513673802;
ans[11][15]=0;
ans[11][16]=881924366;
ans[12][1]=1;
ans[12][2]=233;
ans[12][3]=2131;
ans[12][4]=145601;
ans[12][5]=2332097;
ans[12][6]=106912793;
ans[12][7]=188978103;
ans[12][8]=741005255;
ans[12][9]=528655152;
ans[12][10]=732130620;
ans[12][11]=177126748;
ans[12][12]=150536661;
ans[12][13]=389322891;
ans[12][14]=371114062;
ans[12][15]=65334618;
ans[12][16]=119004311;
ans[13][1]=0;
ans[13][2]=377;
ans[13][3]=0;
ans[13][4]=413351;
ans[13][5]=0;
ans[13][6]=536948224;
ans[13][7]=0;
ans[13][8]=164248716;
ans[13][9]=0;
ans[13][10]=186229290;
ans[13][11]=0;
ans[13][12]=389322891;
ans[13][13]=0;
ans[13][14]=351258337;
ans[13][15]=0;
ans[13][16]=144590622;
ans[14][1]=1;
ans[14][2]=610;
ans[14][3]=7953;
ans[14][4]=1174500;
ans[14][5]=29253160;
ans[14][6]=720246619;
ans[14][7]=124166811;
ans[14][8]=498190405;
ans[14][9]=764896039;
ans[14][10]=274787842;
ans[14][11]=513673802;
ans[14][12]=371114062;
ans[14][13]=351258337;
ans[14][14]=722065660;
ans[14][15]=236847118;
ans[14][16]=451896972;
ans[15][1]=0;
ans[15][2]=987;
ans[15][3]=0;
ans[15][4]=3335651;
ans[15][5]=0;
ans[15][6]=704300462;
ans[15][7]=0;
ans[15][8]=200052235;
ans[15][9]=0;
ans[15][10]=732073997;
ans[15][11]=0;
ans[15][12]=65334618;
ans[15][13]=0;
ans[15][14]=236847118;
ans[15][15]=0;
ans[15][16]=974417347;
ans[16][1]=1;
ans[16][2]=1597;
ans[16][3]=29681;
ans[16][4]=9475901;
ans[16][5]=366944287;
ans[16][6]=289288426;
ans[16][7]=708175999;
ans[16][8]=282756494;
ans[16][9]=416579196;
ans[16][10]=320338127;
ans[16][11]=881924366;
ans[16][12]=119004311;
ans[16][13]=144590622;
ans[16][14]=451896972;
ans[16][15]=974417347;
ans[16][16]=378503901;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值