• [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;
    	}
    };
    
  • 相关阅读:
    Spring Boot 缓存技术:Spring Boot
    Java基础之Iterable接口
    使用sqlyog连接 Mysql 出现1251错误
    IDEA更改主题插件——Material Theme UI详解
    免安装版的Mysql
    使用Nexus搭建Maven私服
    Spring之注解注入bean
    Idea springboot 配置热部署
    Spring Boot 异常处理与单元测试
    Ubuntu20.04在线安装VMware-Tools
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/7998725.html
Copyright © 2020-2023  润新知