题目链接 Clear The Matrix

题意 给定一个$4 * n$的矩形,里面的元素为$'.'$或$'*'$。现在有$4$种正方形可以覆盖掉$'*'$,正方形的边长分别为$1,2,3,4$。

求把整个矩形变成全$'.'$的最小代价。

考虑状压DP

设$f[i][j]$为前$i$列已经全部变成'.',第$i + 1$到第$i + 4$列的这$16$个格子状态为$j$的最小花费。

这$16$个格子标号如下

$0$   $4$   $8$   $12$

$1$   $5$   $9$   $13$

$2$   $6$  $10$  $14$

$3$   $7$  $11$  $15$

我们可以枚举$0,1,2,3$这$4$个格子。以当前格子为左上角的正方形的边长。

其中$0$号格子可以放边长为$0, 1, 2, 3, 4$的正方形;

$1$号格子可以放边长为$0, 1, 2, 3$的正方形;

$2$号格子可以放边长为$0, 1, 2$的正方形;

$3$号格子可以放边长为$0, 1$的正方形;

放边长为$0$的正方形等效为不放。

当枚举的这些正方形可以完全盖住$0,1,2,3$这$4$个格子的时候,就可以进行状态转移。

状态稍微有点复杂,用二进制位表示……

时间复杂度$O(n * 2^{16} * 5!)$

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i) const int N = 1e3 + 10;
const int S = 1 << 16; char s[N];
int f[N][S + 2];
int a[6][N];
int c[10];
int g[10];
int n;
int pre[N];
int ans;
int cnt, mask; void up(int &a, int b){ if (a > b) a = b;}
inline get(int x){ return x ^ (S - 1);} int main(){ scanf("%d", &n);
rep(i, 1, 4) scanf("%d", c + i); rep(i, 1, 4){
scanf("%s", s + 1);
rep(j, 1, n) a[i][j] = s[j] == '*';
} rep(k, 0, n){
rep(i, 0, S + 1) f[k][i] = 1e9;
} cnt = -1;
mask = 0;
rep(i, 1, 4){
rep(j, 1, 4){
++cnt;
if (a[j][i]) mask |= (1 << cnt);
}
}
f[0][mask] = 0; g[0] = 0;
g[1] = 1;
g[2] = (1 << 0) ^ (1 << 1) ^ (1 << 4) ^ (1 << 5);
g[3] = (1 << 0) ^ (1 << 1) ^ (1 << 2);
g[3] ^= ((1 << 4) ^ (1 << 5) ^ (1 << 6));
g[3] ^= ((1 << 8) ^ (1 << 9) ^ (1 << 10));
g[4] = (1 << 16) - 1; rep(k, 0, n){
int extra = 0;
rep(j, 1, 4) if (a[j][k + 5]) extra |= (1 << (j + 11)); rep(j, 0, S - 1){
if (f[k][j] >= 1e9) continue;
rep(aa, 0, 4){
rep(bb, 0, 3){
rep(cc, 0, 2){
rep(dd, 0, 1){
int cnt = get(g[aa]) & get(g[bb] << 1) & get(g[cc] << 2) & get(g[dd] << 3);
if ((cnt & j & 15) == 0){
int nowmask = cnt & j;
nowmask >>= 4;
nowmask ^= extra;
up(f[k + 1][nowmask], f[k][j] + c[aa] + c[bb] + c[cc] + c[dd]);
}
}
}
}
}
}
} ans = 1e9;
rep(i, n - 4, n) ans = min(ans, f[i][0]);
printf("%d\n", ans);
return 0;
}

 

我们可以考虑使用滚动数组,于是空间大大节省

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define MP make_pair
#define fi first
#define se second typedef long long LL; const int N = 1e3 + 10;
const int S = 1 << 16; char s[N];
int f[2][S + 2];
int a[6][N];
int c[10];
int g[10];
int n;
int pre;
int ans;
int cnt, mask; void up(int &a, int b){ if (a > b) a = b;}
inline get(int x){ return x ^ (S - 1);} int main(){ scanf("%d", &n);
rep(i, 1, 4) scanf("%d", c + i); rep(i, 1, 4){
scanf("%s", s + 1);
rep(j, 1, n) a[i][j] = s[j] == '*';
} rep(k, 0, 1) rep(i, 0, S + 1) f[k][i] = 1e9; cnt = -1;
mask = 0;
rep(i, 1, 4){
rep(j, 1, 4){
++cnt;
if (a[j][i]) mask |= (1 << cnt);
}
}
f[0][mask] = 0;
pre = 0; g[0] = 0;
g[1] = 1;
g[2] = (1 << 0) ^ (1 << 1) ^ (1 << 4) ^ (1 << 5);
g[3] = (1 << 0) ^ (1 << 1) ^ (1 << 2);
g[3] ^= ((1 << 4) ^ (1 << 5) ^ (1 << 6));
g[3] ^= ((1 << 8) ^ (1 << 9) ^ (1 << 10));
g[4] = (1 << 16) - 1; rep(i, 0, n){
int extra = 0;
rep(j, 1, 4) if (a[j][i + 5]) extra |= (1 << (j + 11)); rep(j, 0, S + 1) f[pre ^ 1][j] = 1e9; rep(j, 0, S - 1){
if (f[pre][j] >= 1e9) continue;
rep(aa, 0, 4){
rep(bb, 0, 3){
rep(cc, 0, 2){
rep(dd, 0, 1){
int cnt = get(g[aa]) & get(g[bb] << 1) & get(g[cc] << 2) & get(g[dd] << 3);
if ((cnt & j & 15) == 0){
int nowmask = cnt & j;
nowmask >>= 4;
nowmask ^= extra;
up(f[pre ^ 1][nowmask], f[pre][j] + c[aa] + c[bb] + c[cc] + c[dd]);
}
}
}
}
}
}
pre ^= 1;
} printf("%d\n", f[pre][0]);
return 0;
}

不过这个做法还不是最优的= =

官方题解给出的做法是只存后面12个格子的状态的

因为当考虑某一列的时候一旦用到$4*4$的正方形,其他边长的正方形就不用再考虑了……直接无视掉。

这样的话可以直接从$f[k][nowmask]$转移到$f[k + 1][0]$

时间复杂度$O(n * 2^{12} * 96)$

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i) const int N = 1e3 + 10;
const int S = 1 << 12; char s[N];
int f[2][S + 2], a[6][N], c[10], g[10];
int n, x, cnt, mask, ans; void up(int &a, int b){ if (a > b) a = b;}
inline get(int x){ return x ^ (S - 1);} int main(){ scanf("%d", &n);
rep(i, 1, 4) scanf("%d", c + i); rep(i, 1, 4){
scanf("%s", s + 1);
rep(j, 1, n) a[i][j] = s[j] == '*';
} rep(k, 0, 1) rep(i, 0, S + 1) f[k][i] = 1e9; cnt = -1;
mask = 0; rep(i, 1, 3){ rep(j, 1, 4){ ++cnt; if (a[j][i]) mask |= (1 << cnt); }} f[0][mask] = 0;
x = 0; g[0] = 0;
g[1] = 1;
g[2] = 51;
g[3] = 1911; rep(i, 0, n){
int extra = 0;
rep(j, 1, 4) if (a[j][i + 4]) extra |= (1 << (j + 7));
rep(j, 0, S + 1) f[x ^ 1][j] = 1e9; rep(j, 0, S - 1){
if (f[x][j] >= 1e9) continue;
rep(aa, 0, 3){
rep(bb, 0, 3){
rep(cc, 0, 2){
rep(dd, 0, 1){
int cnt = get(g[aa]) & get(g[bb] << 1) & get(g[cc] << 2) & get(g[dd] << 3);
if ((cnt & j & 15) == 0){
mask = (cnt & j) >> 4;
mask ^= extra;
up(f[x ^ 1][mask], f[x][j] + c[aa] + c[bb] + c[cc] + c[dd]);
}
}
}
}
}
up(f[x ^ 1][0], f[x][j] + c[4]);
}
x ^= 1;
} printf("%d\n", f[x][0]);
return 0;
}

Codeforces 903F Clear The Matrix(状态压缩DP)的更多相关文章

  1. Codeforces 903F Clear the Matrix

    题目大意 考虑一个 $4$ 行 $n$ ($4\le n\le 1000$)列的矩阵 $f$,$f$ 中的元素为 * 或 . . 对 $f$ 进行若干次如下变换: 将一个 $k\times k$($1 ...

  2. Codeforces 580D Kefa and Dishes(状态压缩DP)

    题目链接:http://codeforces.com/problemset/problem/580/D 题目大意:有n盘菜每个菜都有一个满意度,k个规则,每个规则由x y c组成,表示如果再y之前吃x ...

  3. Codeforces C. A Simple Task(状态压缩dp)

    题目描述:  A Simple Task time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  4. Codeforces 4538 (状态压缩dp)Little Pony and Harmony Chest

    Little Pony and Harmony Chest 经典状态压缩dp #include <cstdio> #include <cstring> #include < ...

  5. 状态压缩dp(hdu2167,poj2411)

    hdu2167 http://acm.hdu.edu.cn/showproblem.php?pid=2167 给定一个N*N的板子,里面有N*N个数字,选中一些数字,使得和最大 要求任意两个选中的数字 ...

  6. Light OJ 1316 A Wedding Party 最短路+状态压缩DP

    题目来源:Light OJ 1316 1316 - A Wedding Party 题意:和HDU 4284 差点儿相同 有一些商店 从起点到终点在走过尽量多商店的情况下求最短路 思路:首先预处理每两 ...

  7. Light OJ 1406 Assassin`s Creed 状态压缩DP+强连通缩点+最小路径覆盖

    题目来源:Light OJ 1406 Assassin`s Creed 题意:有向图 派出最少的人经过全部的城市 而且每一个人不能走别人走过的地方 思路:最少的的人能够走全然图 明显是最小路径覆盖问题 ...

  8. HDU 6125 Free from square 状态压缩DP + 分组背包

    Free from square Problem Description There is a set including all positive integers that are not mor ...

  9. 状态压缩dp初学__$Corn Fields$

    明天计划上是要刷状压,但是作为现在还不会状压的\(ruoruo\)来说是一件非常苦逼的事情,所以提前学了一下状压\(dp\). 鸣谢\(hmq\ juju\)的友情帮助 状态压缩动态规划 本博文的大体 ...

随机推荐

  1. git 使用规范

    git使用资料: https://github.com/peak-c/my-git 公司内部使用开发规范: 一. 代码库介绍 个人开发库(git@gitlab.adrd.sohuno.com:sper ...

  2. Python linecache模块

    Table of Contents 1. linecache 1.1. 其它 2. 参考资料 linecache 今天分享一个python的小模块: linecache, 可以用它方便地获取某一文件某 ...

  3. RCP 项目启动图片设置

    第一步 选择启动图片命名为 splash.bmp 第二步 添加 扩展点 然 后在右边的扩展元素细节中填入相应的信息,比如我们在这里的application属 性 为 org.vwpolo.rcp.ex ...

  4. easyui-numberbox限定仅输入数字

    许多必填项都涉及到数字,比如电话号码,身份证号这些要求用户在输入时只能输入数字.Easyui提供了数字框控件,允许用户只输入数字, <td> <input id="ssd& ...

  5. IOS笔记048-数据存储

      IOS数据存储的几种方式         XML属性列表(plist)         归档 Preference(偏好设置)          NSKeyedArchiver归档(NSCodin ...

  6. 一个iOS程序员眼中的跨域问题

    摘要: 跨域问题是web开发领域一个常见的问题,相信每个web开发者都遇到"跨域"的问题 最近公司的iOS开发任务比较少,所以自己最近开始了Web开发的任务,在用H5做了很多页面, ...

  7. win7分盘(复制)

    1/10 右击“计算机”选择“管理” 2/10 打开管理之后点击“磁盘管理器”,在想要新建磁盘的分区上右击,点击“压缩卷” 3/10 在“输入压缩空间量”后面输入需要新建磁盘的大小,输入的单位为MB( ...

  8. X-UA-Compatible设置IE浏览器兼容模式

    文件兼容性用来告诉IE,让它如何来编译你的网页. 指定 文件兼容性模式 以下是指定为Emulate IE7 mode 兼容性范例. <html> <head> <!-- ...

  9. File IO(NIO.2):读、写并创建文件

    简介 本页讨论读,写,创建和打开文件的细节.有各种各样的文件I / O方法可供选择.为了帮助理解API,下图以复杂性排列文件I / O方法 在图的最左侧是实用程序方法readAllBytes,read ...

  10. 禁用jQuery chosen的选择下拉菜单

    想法是启用被勾掉之后,左侧下拉框禁用.这是chosen()的 disabled之后需要更新一下.就这样,还有别的方法的话请分享,O(∩_∩)O哈哈~