zoukankan      html  css  js  c++  java
  • UVA 11741 Ignore the Blocks

    https://vjudge.net/problem/UVA-11741

    题目

    给一个$n$行$m$列的棋盘,上面有一些坏格子(最多100个),剩下的都是好格子,你有充足的$1 imes2$骨牌,问把所有好格子都不重不漏地覆盖同时不能覆盖坏格子的方法有多少个,$1leqslant nleqslant 4, 1leqslant mleqslant 100000000$,输出对10000007取模后的结果。

    题解

    第一次我直接轮廓线dp到末尾,然后就TLE了……

    因为坏格子比较少,行数也很少,因此把行压成一个状态,计算两行状态之间的转移,得到一个矩阵,然后就可以通过矩阵幂计算了……

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<cctype>
    #define REP(i,a,b) for(register unsigned i=(a); i<(b); i++)
    #define REPE(i,a,b) for(register unsigned i=(a); i<=(b); i++)
    #define PERE(i,a,b) for(register unsigned i=(a); i>=(b); i--)
    using namespace std;
    typedef long long ll;
    struct node {
    	int a, b;
    	bool operator<(const node&r) const {
    		return b<r.b;
    	}
    };
    #define MAXN 107
    #define MO 10000007
    node bdcol[MAXN];//记录坏格子
    int dp[2][16];//计算转移用的
    int mtx[5][16][16];//转移矩阵
    int ones[5][16][16];//单位矩阵
    inline void db() {
    	memset(ones,0,sizeof(ones));
    	REP(r,1,5) {
    		unsigned msk=1<<r, m=msk>>1;
    		REP(i,0,msk) {
    			ones[r][i][i]=1;
    		}
    		REP(f,0,msk) {
    			memset(dp[0],0,sizeof(dp[0]));
    			dp[0][f]=1;
    			int now=0;
    			REP(i,0,r) {
    				now^=1; memset(dp[now],0,sizeof(dp[now]));
    				REP(k,0,msk) {
    					if(k&1) dp[now][k>>1]+=dp[now^1][k];
    					if(!(k&1)) dp[now][(k>>1)|m]+=dp[now^1][k];
    					if(i && (k&1) && !(k&m)) dp[now][((k|m)>>1)|m]+=dp[now^1][k];
    				}
    			}
    			REP(t,0,msk) {
    				mtx[r][f][t]=dp[now][t];
    			}
    		}
    	}
    }
    int r,c,n;
    unsigned msk, m;
    inline void mul(const int a[16][16], const int b[16][16], int ret[16][16]) { //矩阵乘法
    	int ans[16][16];
    	REP(i,0,msk) {
    		REP(j,0,msk) {
    			ans[i][j]=0;
    			REP(k,0,msk) {
    				ans[i][j]=(ans[i][j]+((ll)a[i][k]*b[k][j]))%MO;
    			}
    		}
    	}
    	memcpy(ret,ans,sizeof(ans));
    }
    inline void qpow(const int a[16][16], int y, int ret[16][16]) { //矩阵幂
    	int ans[16][16];
    	int x[16][16];
    	memcpy(x,a,sizeof(x));
    	memcpy(ans,ones[r],sizeof(ans));
    	for(;y;y>>=1) {
    		if(y&1) mul(ans,x,ans);
    		mul(x,x,x);
    	}
    	memcpy(ret,ans,sizeof(ans));
    }
    int A[16][16];
    int B[16][16];
    int main() {
    	int kase=1;
    	db();
    	while(~scanf("%d%d%d", &r, &c, &n) && r) {
    		msk = 1u<<r; m=msk>>1;
    		REP(i,0,n) {
    			scanf("%d%d", &bdcol[i].a, &bdcol[i].b);
    		}
    		REP(i,0,r) {
    			bdcol[n].a=i, bdcol[n].b=c;
    			n++;
    		}
    		sort(bdcol,bdcol+n);
    		int now=0, from=-1;//当前坏格子编号和列
    		memcpy(A,ones[r],sizeof(A));
    		int i=0;
    		while(i<n) {
    			now=i;
    			unsigned k=0;
    			while(i<n && bdcol[i].b==bdcol[now].b) {k|=1<<bdcol[i].a; i++;}
    			qpow(mtx[r], bdcol[now].b-from, B); //B=F^{...}
    			mul(A,B,A);
    			memset(B,0,sizeof(B));
    			REP(i,0,msk) REP(j,0,msk) if(!(j&k)) {
    				B[i][j|k]+=A[i][j];
    			}
    			memcpy(A,B,sizeof(A));
    			from = bdcol[now].b;
    		}
    		
    		printf("Case %d: %d
    ", kase, A[msk-1][msk-1]);//从-1排满到最后一排满
    		kase++;
    	}
    	return 0;
    }
    
  • 相关阅读:
    深入Android 【一】 —— 序及开篇
    Android中ContentProvider和ContentResolver使用入门
    深入Android 【六】 —— 界面构造
    The service cannot be activated because it does not support ASP.NET compatibility. ASP.NET compatibility is enabled for this application. Turn off ASP.NET compatibility mode in the web.config or add the AspNetCompatibilityRequirements attribute to the ser
    Dynamic Business代码片段总结
    对文件的BuildAction以content,resource两种方式的读取
    paraview 3.12.0 windows下编译成功 小记
    百度网盘PanDownload使用Aria2满速下载
    netdata的安装与使用
    用PS给证件照排版教程
  • 原文地址:https://www.cnblogs.com/sahdsg/p/12328067.html
Copyright © 2011-2022 走看看