[codevs1050]棋盘染色 2

试题描述

有一个5*N的棋盘,棋盘中的一些格子已经被染成了黑色,你的任务是对最少的格子染色,使得所有的黑色能连成一块。

输入

第一行一个整数N(<=100),接下来N行每行一个长度为5的01串,1表示所在格子已经被染成了黑色,0表示所在格子没有被染色。

输出

输出最少需要对多少个格子进行染色

输入示例


输出示例


数据规模及约定

N(<=100)

题解

状压 dp 一下。设 f(i, S) 表示考虑前 i 行,最后一行情况为集合 S 的最小代价;其中 S 是一个 5 位的 4 进制数,若某一位为 0,则表示第 i 行对应的位置没有染色,若某一位为 x(0 < x < 4),则表示该位上有染色并且该位置所在的连通分量编号为 x(注意这里的连通分量是指考虑前 i 行时的连通性,因为最终要做到整个图被弄成一个连通分量,所以任意时刻同一连通块必定能够贯穿上下),一行中只有 5 个位置,所以最多产生 3 个连通块,也就是每一位上只可能是 0, 1, 2, 3,所以是 5 位的 4 进制数。

转移时枚举一下下一行在哪些位置染色,然后暴力搞一搞判一判就好了。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std; int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
} #define maxn 110
#define maxm 10
char Map[maxn][maxm];
int n, A[maxn][maxm], f[maxn][1030], now[maxm], lst[maxm], fin[maxm], tfin[maxm]; bool iszero(char* S) {
int l = strlen(S);
for(int i = 0; i < l; i++) if(S[i] - '0') return 0;
return 1;
}
int bitcal(int S) {
int cnt = 0;
while(S) cnt += (S & 1), S >>= 1;
return cnt;
}
void Up(int& a, int b) {
if(a < 0) a = b;
else a = min(a, b);
return ;
} void show(int T[]) {
for(int i = 0; i < 5; i++) printf("%d%c", T[i], i < 4 ? ' ' : '\n');
return ;
} int main() {
n = read();
for(int i = 1; i <= n; i++) scanf("%s", Map[i]); int up = 1, down = n, cnt = 0;
while(iszero(Map[up])) up++;
while(iszero(Map[down])) down--;
for(int i = up; i <= down; i++) {
cnt++;
for(int j = 0; j < 5; j++) A[cnt][j] = Map[i][j] - '0';
}
memset(f, -1, sizeof(f));
f[0][0] = 0;
int all = (1 << 5) - 1, All = (1 << 10) - 1;
for(int i = 1; i <= cnt; i++) {
int reaS = 0;
for(int j = 4; j >= 0; j--) reaS = reaS << 1 | A[i][j];
for(int S = 0; S <= all; S++) if((reaS | S) == S) {
int cnt1 = bitcal(reaS ^ S);
for(int j = 0; j < 5; j++) now[j] = S >> j & 1;
for(int tS = 0; tS <= All; tS++) if(f[i-1][tS] >= 0) {
int tmpS = tS;
for(int j = 0; j < 5; j++) lst[j] = tmpS % 4, tmpS >>= 2;
int mx = 0;
for(int j = 0; j < 5; j++) if(now[j]) {
if(!j) mx = fin[j] = 1;
else if(!fin[j-1]) fin[j] = ++mx;
else fin[j] = fin[j-1];
}
else fin[j] = 0;
// printf("%d _fin: ", cnt1); show(fin);
mx = 0;
for(int j = 0; j < 5; j++) mx = max(mx, lst[j]);
int has[maxm]; memset(has, 0, sizeof(has));
for(int j = 0; j < 5; j++) if(lst[j]) {
if(!has[lst[j]] && fin[j]) has[lst[j]] = fin[j];
else if(fin[j]) {
fin[j] = has[lst[j]];
for(int x = j - 1; x >= 0 && fin[x]; x--) fin[x] = has[lst[j]];
for(int x = j + 1; x < 5 && fin[x]; x++) fin[x] = has[lst[j]];
}
}
bool ok = 1;
for(int j = 1; j <= mx; j++) if(!has[j]) {
ok = 0; break;
}
if(!ok) continue;
for(int j = 0; j < 5; j++) tfin[j] = fin[j];
sort(tfin, tfin + 5);
int x = unique(tfin, tfin + 5) - tfin;
if(x > 1) for(int j = 0; j < 5; j++) fin[j] = lower_bound(tfin, tfin + x, fin[j]) - tfin;
// show(now); show(lst); show(fin);
tmpS = 0;
for(int j = 4; j >= 0; j--) tmpS = tmpS << 2 | fin[j];
Up(f[i][tmpS], f[i-1][tS] + cnt1);
// printf("%d\n", f[i][tmpS]); putchar('\n');
}
}
} int ans = -1;
for(int S = 0; S <= all; S++) {
for(int i = 0; i < 5; i++) now[i] = S >> i & 1;
int reaS = 0;
for(int i = 4; i >= 0; i--) reaS = reaS << 2 | now[i];
if(f[cnt][reaS] >= 0) Up(ans, f[cnt][reaS]);
}
printf("%d\n", ans); return 0;
}

写个状压 dp 真费劲。。。

[codevs1050]棋盘染色 2的更多相关文章

  1. [CodeVs1050]棋盘染色2(状态压缩DP)

    题目大意:有一个5*N(≤100)的棋盘,棋盘中的一些格子已经被染成了黑色,求最少对多少格子染色,所有的黑色能连成一块. 这题卡了我1h,写了2.6k的代码,清明作业一坨还没做啊...之前一直以为这题 ...

  2. codevs——1049 棋盘染色

    1049 棋盘染色  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解  查看运行结果     题目描述 Description 有一个5×5的棋盘,上面有一 ...

  3. 【wikioi】1049 棋盘染色(迭代深搜)

    http://www.wikioi.com/problem/1049/ 这题我之前写没想到迭代加深,看了题解,然后学习了这种搜索(之前我写的某题也用过,,但是不懂专业名词 囧.) 迭代加深搜索就是限制 ...

  4. codevs 1049 棋盘染色

    题目描述 Description 有一个5×5的棋盘,上面有一些格子被染成了黑色,其他的格子都是白色,你的任务的对棋盘一些格子进行染色,使得所有的黑色格子能连成一块,并且你染色的格子数目要最少.读入一 ...

  5. 1050 棋盘染色 2 - Wikioi

    题目描述 Description 有一个5*N的棋盘,棋盘中的一些格子已经被染成了黑色,你的任务是对最少的格子染色,使得所有的黑色能连成一块. 输入描述 Input Description 第一行一个 ...

  6. HDU 5402 Travelling Salesman Problem(棋盘染色 构造 多校啊)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5402 Problem Description Teacher Mai is in a maze wit ...

  7. CODEVS——T 1049 棋盘染色

    http://codevs.cn/problem/1049/  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解  查看运行结果     题目描述 Descr ...

  8. hdu5601-N*M bulbs(黑白棋盘染色)

    一个矩形,一个人从左上角走到右下角,每走过一个位置把0变成1,1变成0. 求有没有可能他离开之后所有的数都是0 假设这个矩形是一个棋盘,黑白相间. 这样会发现从一个颜色走到相同颜色可以对棋盘不产生任何 ...

  9. [codevs1049]棋盘染色<迭代深搜>

    题目链接:http://codevs.cn/problem/1049/ 昨天的测试题里没有打出那可爱的迭代深搜,所以今天就来练一练. 这道题其实我看着有点懵,拿着题我就这状态↓ 然后我偷偷瞄了一眼hz ...

随机推荐

  1. 让搜狗输入法更符合编程/vim使用的配置

    1. “菜单”—“设置属性”—“常用”—“初始状态”里的“中/英文”选项,选中“英文” 2. 设置属性里的“高级”里的“高级模式”,点“英文输入法设置”,“启动时启用英文输入法”选中 3. 按键-中英 ...

  2. java 替换字符串模板(模板渲染)

    java渲染字符串模板,也就是说在java字符串模板中设置变量字符串,使用变量去渲染指定模板中设置好的变量字符串.下面介绍4种替换模板方式: 1.使用内置String.format String me ...

  3. input标签属性

    很多时候,我们都用到了很多标签实现输入功能,所以在这里梳理一下. 1.建立一个文本框 <input type="text" name="userName" ...

  4. Some Python Tricks

    python 的包管理很不好用,理解费力,故偷懒,模块仍按文件布局,写一个合并脚本将各个模块合并输出到一个脚本文件,分别管理,合并输出,回避了加载模块的问题 f-format 仅在python 3.6 ...

  5. AJPFX浅谈Java 性能优化之垃圾回收(GC)

    ★JVM 的内存空间 在 Java 虚拟机规范中,提及了如下几种类型的内存空间: ◇栈内存(Stack):每个线程私有的.◇堆内存(Heap):所有线程公用的.◇方法区(Method Area):有点 ...

  6. [BZOJ2705][SDOI2012]Longge的问题 数学

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2705 首先分析得题目所求$gcd(i,N)$的取值只可能是$N$的因子,则有$$Ans=\ ...

  7. 登录脚本重构Element

    登录脚本重构Element package com.gubai.selenium; import org.openqa.selenium.By; import org.openqa.selenium. ...

  8. COGS 886. [USACO 4.2] 完美的牛栏

    ★★☆   输入文件:stall4.in   输出文件:stall4.out   简单对比时间限制:1 s   内存限制:128 MB USACO/stall4(译by Felicia Crazy) ...

  9. 【Conclusion】MySQL的安装和使用

    MySQL使用 因为数据库实验用到了MySQL,这里对现在已经涉及到的MySQL部分操作做一个简单的小结. 1.安装MySQL 上MySQL的官网下载对应自己OS平台的MySQL安装文件,有在线安装和 ...

  10. dom和bom是什么?

    DOM:文档对象模型,描述了处理网页内容的方法和接口.最根本对象是document(window.document). 由于DOM的操作对象是文档,所以DOM和浏览器没有直接关系. 部署在服务器上的文 ...