zoukankan      html  css  js  c++  java
  • [TC_SRM_466]DrawingBlackCrosses

    [TC_SRM_466]DrawingBlackCrosses

    试题描述

    (n imes m)(n, m le 20))的棋盘

    其中至多有 (8) 个格子为黑色,其他格子为白色

    每次可以选一个白格子把它所在的行、列包括它本身变成黑色

    求把棋盘全变成黑色的操作方案数

    输入

    传给你一个 string[] 类型的参数

    输出

    返回一个整数表示答案

    输入示例

    {"B..B", "B.B.", "...B", "BB.B", "...."}
    

    输出示例

    Returns: 324
    

    数据规模及约定

    见“试题描述

    题解

    由于黑格子不超过 (8) 个,并且每次操作都是整行整列变黑,所以可以任意交换行列,不会影响最终结果。

    于是我们可以把它交换成左上角最多 (8 imes 8) 区域内有黑格子,剩下一个反 (L) 型的全白区域。

    对于全白区域,我们只需要关心它有几行几列就行了;而对于有黑格子的地方就需要用状压。

    于是令 (f(s_x, s_y, i, j)) 表示对于有黑格子的区域行覆盖的集合是 (s_x),列覆盖集合为 (s_y),全白区域覆盖了 (i)(j) 列,然后转移显然。

    最后累计答案时需要开个数组模拟一下确定哪些状态是最终状态。(好像也可以看哪些状态没有后继状态吧,这样快一点,但是我不管了。这题搞了我一个上午,弄得我生活不能自理

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    #include <vector>
    using namespace std;
    #define rep(i, s, t) for(int i = (s); i <= (t); i++)
    #define dwn(i, s, t) for(int i = (s); i >= (t); i--)
    
    const int maxspace = 12010101, maxn = 21, MOD = 1000000007;
    #define LL long long
    
    int n, m, bn, bm, sn, sm, _x[maxn*maxn], _y[maxn*maxn], cb, xnum[maxn*maxn], ynum[maxn*maxn];
    char Map[maxn][maxn];
    bool g[maxn][maxn], tg[maxn][maxn];
    
    int F[maxspace];
    #define f(si, sj, i, j) F[(si)*(sm+1)*(n-bn+1)*(m-bm+1)+(sj)*(n-bn+1)*(m-bm+1)+(i)*(m-bm+1)+(j)]
    class DrawingBlackCrosses {
    	public:
    	int count(vector <string> field) {
    		n = field.size(); m = field[0].length();
    		rep(i, 0, n - 1) strcpy(Map[i], field[i].c_str());
    		
    		rep(i, 0, n - 1) rep(j, 0, m - 1) if(Map[i][j] == 'B') {
    			_x[cb] = i; _y[cb++] = j;
    			xnum[bn++] = i; ynum[bm++] = j;
    		}
    		sort(xnum, xnum + bn); sort(ynum, ynum + bm);
    		bn = unique(xnum, xnum + bn) - xnum; bm = unique(ynum, ynum + bm) - ynum;
    		sn = (1 << bn) - 1; sm = (1 << bm) - 1;
    		rep(i, 0, cb - 1) {
    			_x[i] = lower_bound(xnum, xnum + bn, _x[i]) - xnum;
    			_y[i] = lower_bound(ynum, ynum + bm, _y[i]) - ynum;
    			g[_x[i]][_y[i]] = 1;
    		}
    		int sx = 0, sy = 0, fullx = 0, fully = 0; // all_black
    		rep(i, 0, n - 1) {
    			bool ab = 1;
    			rep(j, 0, m - 1) if(!g[i][j]){ ab = 0; break; }
    			if(ab && i < bn) sx |= 1 << i;
    			ab = 1;
    			rep(j, 0, bm - 1) if(!g[i][j]){ ab = 0; break; }
    			if(i < bn) fullx |= (int)ab << i;
    		}
    		rep(j, 0, m - 1) {
    			bool ab = 1;
    			rep(i, 0, n - 1) if(!g[i][j]){ ab = 0; break; }
    			if(ab && j < bm) sy |= 1 << j;
    			ab = 1;
    			rep(i, 0, bn - 1) if(!g[i][j]){ ab = 0; break; }
    			if(j < bm) fully |= (int)ab << j;
    		}
    		f(sx, sy, n - bn, m - bm) = 1;
    		rep(si, 0, sn) rep(sj, 0, sm) dwn(i, n - bn, 0) dwn(j, m - bm, 0) if(f(si, sj, i, j)) {
    			int now = f(si, sj, i, j), tsi, tsj, ti, tj;
    			rep(ini, 0, bn) rep(inj, 0, bm) {
    				if(ini < bn) tsi = si | (1 << ini), ti = i;
    				else tsi = si, ti = i - 1;
    				if(inj < bm) tsj = sj | (1 << inj), tj = j;
    				else tsj = sj, tj = j - 1;
    				if(ini < bn && inj < bm && !g[ini][inj] && !(si >> ini & 1) && !(sj >> inj & 1)) (f(tsi, tsj, ti, tj) += now) %= MOD;
    				if(ini < bn && inj == bm && !(si >> ini & 1) && j > 0) (f(tsi, tsj, ti, tj) += (LL)now * j % MOD) %= MOD;
    				if(ini == bn && inj < bm && i > 0 && !(sj >> inj & 1)) (f(tsi, tsj, ti, tj) += (LL)now * i % MOD) %= MOD;
    				if(ini == bn && inj == bm && i > 0 && j > 0) (f(tsi, tsj, ti, tj) += (LL)now * i % MOD * j % MOD) %= MOD;
    			}
    		}
    		
    		int ans = 0;
    		rep(si, 0, sn) rep(sj, 0, sm) rep(i, 0, n - bn) rep(j, 0, m - bm) if(f(si, sj, i, j)) {
    			memcpy(tg, g, sizeof(g));
    			rep(x, 0, bn - 1) if(si >> x & 1)
    				rep(y, 0, m - 1) tg[x][y] = 1;
    			rep(y, 0, bm - 1) if(sj >> y & 1)
    				rep(x, 0, n - 1) tg[x][y] = 1;
    			dwn(x, n - 1, n - (n - bn - i)) rep(y, 0, m - 1) tg[x][y] = 1;
    			dwn(y, m - 1, m - (m - bm - j)) rep(x, 0, n - 1) tg[x][y] = 1;
    			bool all1 = 1;
    			rep(x, 0, n - 1) rep(y, 0, m - 1) if(!tg[x][y]){ all1 = 0; break; }
    			if(all1) (ans += f(si, sj, i, j)) %= MOD;
    		}
    		
    		return ans;
    	}
    };
    
  • 相关阅读:
    linux下shell显示-bash-4.1#不显示路径解决方法
    update chnroute
    An error "Host key verification failed" when you connect to other computer by OSX SSH
    使用dig查询dns解析
    DNS被污染后
    TunnelBroker for EdgeRouter 后记
    mdadm详细使用手册
    关于尼康黄的原因
    Panda3d code in github
    Python实例浅谈之三Python与C/C++相互调用
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/7998725.html
Copyright © 2011-2022 走看看