Sicily 14254. Wall Painting

14254. Wall Painting

Constraints

Time Limit: 1 secs, Memory Limit: 256 MB

Description

A wall looks dirty, so Alpha has been sent there to repaint it in order to make it clean.

The wall is H feet tall and W feet wide, so Alpha first divide it into H*W regions per square foot and then starts his repaint, in other words, the wall‘s surface is divide into H rows and W columns.

Alpha is a lazy boy, he have found that some regions looks not so dirty so it does not need to be cleaned, and because he is a lazy boy, he will declare his work is done when he notice that each column of the wall has no more
than 2 regions remains dirty.

The way that Alpha cleans this wall is special. At each step, Alpha will choose a row and repaint it from left to right. After he has finished this step, all regions in this row will become white and clean. He just keeps repeating
this kind of step several times until he thinks his job is done.

Now Alpha wants to know how many rows he should repaint at least. This is an easy problem, could you tell him the answer?

Input

Input contains multiple test cases, terminated by EOF.

Each test case starts with two integer H and W (3<=H<=15, 3<=W<=40), indicating the wall‘s height and width. The following H lines each have W digits ‘0‘ or ‘1‘, describing the status of the wall‘s regions. If the j-th character
in the i-th line is ‘1‘, it means that the corresponding region on the wall (the j-th column in the i-th row) looks not so clean and might need to be repainted; otherwise it looks not so dirty and Alpha can either repaint or not repaint it.

Output

For each case, output the minimum number of rows Alpha should repaint in a line.

Sample Input

3 31111111114 510100110100110100011

Sample Output

10

Problem Source

SYSUCPC 2014 Preliminary (Online) Round

#include <stdio.h>
#include <string.h>

int H, W;
char wall[20][45];
int ans;
bool cleaned[20];

bool isOK() {
	for (int i = 0; i < W; i++) {
		int num = 0;
		for (int j = 0; j < H; j++) {
			if (wall[j][i] == '1') num++;
			if (num > 2) break;
		}
		if (num > 2) return false;
	}
	return true;
}

void dfs(int cleanedPos, int cleanedNum) {
	if (cleanedPos == H) {
		if (isOK() && cleanedNum < ans) ans = cleanedNum;
		return;
	}
	dfs(cleanedPos + 1, cleanedNum);
	char record[45];
	for (int j = 0; j < W; j++) record[j] = wall[cleanedPos][j];
	for (int j = 0; j < W; j++) wall[cleanedPos][j] = '0';
	dfs(cleanedPos + 1, cleanedNum + 1);
	for (int j = 0; j < W; j++) wall[cleanedPos][j] = record[j];
}

int main() {

	while (scanf("%d%d\n", &H, &W) != EOF) {
		for (int i = 0; i < H; i++) gets(wall[i]);
		ans = H;
		memset(cleaned, false, sizeof(cleaned));
		dfs(0, 0);
		printf("%d\n", ans);
	}

	return 0;
}
时间: 2025-01-20 06:02:36

Sicily 14254. Wall Painting的相关文章

HDU - 4810 Wall Painting(组合数学)

Description Ms.Fang loves painting very much. She paints GFW(Great Funny Wall) every day. Every day before painting, she produces a wonderful color of pigments by mixing water and some bags of pigments. On the K-th day, she will select K specific bag

hdu 4810 Wall Painting (组合数学+二进制)

题目链接 下午比赛的时候没有想出来,其实就是int型的数分为30个位,然后按照位来排列枚举. 题意:求n个数里面,取i个数异或的所有组合的和,i取1~n 分析: 将n个数拆成30位2进制,由于每个二进制位异或后相加和原来的数异或相加是一样的,所以只需要对每一位累加计算,用组合数学取数就行了,奇数个异或得1,偶数个异或得0,再乘以自己的二进制位值,复杂度O(30*n*n) 1 #include <iostream> 2 #include <cstdio> 3 #include <

HDU 4810 Wall Painting(异或 +按位容斥)

直接不会,预估时间复杂度,对于C(n,m) 到规模为500就瞎了.当时也想算法应该接近常数级别的. 如果真的算必然跪.回头看了下解题报告. 话说比赛很喜欢考异或,"位"思想,组合问题 对于计算选取k个数字时候,分别计算各个位上可能出现的情况,然后计算各个位上的累加和.即便一个数字可由很多位组成但是每次计算一个位 记录每一位上1的个数(这里只需要32位),对于第i天,必须要选出奇数个1才能使该位异或结果位1,否则为0.我们来看样例, 4 1 2 10 1 这4个数的二进制表示分别为: 0

hdu 4810 Wall Painting

http://acm.hdu.edu.cn/showproblem.php?pid=4810 把每一个数转化二进制,然后统计n个数在每一位的1的个数.奇数个1异或才能得1,然后用组合数,计算. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 const int mod=1000003; 6 7 int n; 8 __int64 a[1100]

HDU 4810 Wall Painting (位操作-异或)

OJ题目:click here~~ 题目分析:给n个数.从这n个数中选择i个数,共同拥有c(n , i)种情况.将每种情况中的i个数异或,将这c(n , i)个异或结果求和,就得到第i个输出结果,i属于[1  n]. 求x个数的异或,等于分别对x个数的同一二进制位进行异或,然后加权求和. 于是将n个数表示成二进制的形式.对于本题,32位就够. 由于,奇数个1的异或 = 1 , 偶数个1的异或 = 0 . 统计每位上1的个数 .然后对于第j个二进制位.枚举所选中的1的个数.加权求和,就可以得结果.

HDU 4810 Wall Painting【二进制+异或+暴力枚举】

给出n个数 求从这n个数取k个数异或,所有情况得到的值(Cnk个值(可能有些相同))全加起来的值是多少 k从1到n 输出这n个数 这题一开始想毫无思绪 也没有说这n个数的大概范围,想用背包来着本来 结果发现它是这么解的 就样例来说,把四个数1,2,10,1拆开,当前是取k个数 0001 0010 1010 0001 对第四位来说,如果某些方案是取k个数异或后为0,那么等于 0*方案数,这个我们可以不用管它 如果某些方案是取2个数异或后为1,那么等于1*方案数 可以看到第四位有1个1,那么异或为1

hdu-4810 Wall Painting 2013ACM/ICPC亚洲区南京站现场赛

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=4810 解题思路: 记录下每个数的各个位上1个数的和,根据题意,异或要产生数值,必须是取基数个1,通过组合数学的方法,比如要在6个1里面取三个1,则取得方法有C(6,3),那么如何可以快速取得C(6,3)呢?通过杨辉三角形打表即可 #include <iostream> #include <cstdio> #include <cstring> using namespace s

2015.11.8 ---2013.南京

GPA 算绩点 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 int n; 8 string p[15] = {"A","A-","B+","B","B-", 9 "C+"

劳动节的玩具。。

第一题 987654321 problem 水题,打个表找个规律,一瞬间就好了.. #include<cstdio> #include<iostream> using namespace std; int main() { /*for(long long i=1000;i<=0x7ffffffff;i++) { if((i*i)%1000000000==987654321) { cout<<i<<endl; } }*/ int n; cin>&g