poj_3185 反转问题

题目大意

有20个碗排成一排,有些碗口朝上,有些碗口朝下。每次可以反转其中的一个碗,但是在反转该碗时,该碗左右两边的碗也跟着被反转(如果该碗为边界上的碗,则只有一侧的碗被反转)。求最少需要反转几次,可以使得所有碗口均朝上。

题目分析

类似黑白染色问题(将一个格子染色,其上下左右四个格子也被染成分别相反的颜色),找到规律之后可以不用进行暴力枚举搜索。 
    考虑最左边的那个碗,该碗要么被反转要么不被反转,只有两种可能。对于任何一种可能继续考虑:对于碗1,如果碗0口朝下,则只有碗1能够将其反转(因为碗0已经考虑过了),因此碗1必须反转。同样继续考虑碗2(看碗1是否口朝下)....直到最后一个碗。 
    因此,碗0反转和不反转分别只对应一种20个碗的反转情况。这种看似情况很多的问题,在合理性的剪枝之下,其实合法的状态很少,且合法的状态是可以由开始的状态推出来的。

实现(c++)

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<cmath>
using namespace std;
int bowl[25];
int bowl2[25];
int main(){
	while (scanf("%d", &bowl[0]) != EOF){

		bowl2[0] = bowl[0];
		for (int i = 1; i < 20; i++){
			scanf("%d", &bowl[i]);
			bowl2[i] = bowl[i];
		}
		int flip_count = 0;
		//not flip position 0
		for (int i = 1; i < 20; i++){
			if (bowl[i - 1]){
				flip_count++;
				bowl[i - 1] = 0;
				bowl[i] = 1 - bowl[i];
				bowl[i + 1] = 1 - bowl[i + 1];
			}
		}
		int min_flip = flip_count;
		if (bowl[19] == 1){
			min_flip = 10000;
		}
		//flip bowl 0
		flip_count = 1;
		bowl2[0] = 1 - bowl2[0];
		bowl2[1] = 1 - bowl2[1];
		for (int i = 1; i < 20; i++){
			if (bowl2[i - 1]){
				flip_count++;
				bowl2[i - 1] = 0;
				bowl2[i] = 1 - bowl2[i];
				bowl2[i + 1] = 1 - bowl2[i + 1];
			}
		}

		if (bowl2[19] == 0){
			min_flip = min_flip < flip_count ? min_flip : flip_count;
		}
		printf("%d\n", min_flip);
	}
	return 0;
}
时间: 2025-02-01 20:03:35

poj_3185 反转问题的相关文章

1.5编程基础之循环控制_29:数字反转

/* 1.5编程基础之循环控制 29:数字反转 总时间限制: 1000ms 内存限制: 65536kB 描述 给定一个整数,请将该数各个位上数字反转得到一个新数. 新数也应满足整数的常见形式,即除非给定的原数为零, 否则反转后得到的新数的最高位数字不应为零(参见样例2). 输入 输入共 1 行,一个整数N. -1,000,000,000 ≤ N≤ 1,000,000,000. 输出 输出共 1 行,一个整数,表示反转后的新数. 样例输入 样例 #1: 123 样例 #2: -380 样例输出 样

拼接字符串;字符反转;统计大串中小串出现的次数

package Homework; import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.Scanner;/** * 把数组中的数据按照指定个格式拼接成一个字符串举例:int[] arr = {1,2,3}; 输出结果:[1, 2, 3] 字符串反转举例:键盘录入"abc" 输出结果:"cba" 统计大串中小串出现的次数举例:在字符串&q

反转波兰计算器

#include <iostream>using namespace std;typedef double stackEntry; const int overflow = 1;const int underflow = 2;const int success = 0; const int maxstack = 100;//栈的最大尺寸class stack{public: stack(); int pop(); int push(const stackEntry &item); in

iOS控制反转(IoC)与依赖注入(DI)的实现

背景 最近接触了一段时间的SpringMVC,对其控制反转(IoC)和依赖注入(DI)印象深刻,此后便一直在思考如何使用OC语言较好的实现这两个功能.Java语言自带的注解特性为IoC和DI带来了极大的方便,要在OC上较好的实现这两个功能,需要一些小小的技巧. 控制反转和依赖注入 控制反转 简单来说,将一个类对象的创建由手动new方式改为从IOC容器内获取,就是一种控制反转,例如我们现在要创建一个ClassA类,则常规方法为 ClassA *a = [ClassA new]; 如果使用控制反转,

工厂模式、控制反转及依赖注入

在介绍工厂模式与控制反转(Inversion of Control)及依赖注入(Dependency Injection)之前,先介绍下类的调用方法.目前调用方法总共有3种:1.自己创建:2.工厂模式:3.外部注入,其中外部注入即为控制反转/依赖注入模式(IoC/DI).我们可以用3个形象的东西来分别表示它们,就是new.get.set.顾名思义,new表示自己创建,get表示主动去取(即工厂),set表示是被别人送进来的(即注入),其中get和set分别表示了主动去取和等待送来两种截然相反的特

Reverse Integer - 反转一个int,溢出时返回0

Reverse Integer Reverse digits of an integer. Example1: x = 123, return 321Example2: x = -123, return -321 若反转的数溢出,直接返回0 可以用计算结果来判断溢出,也可以用因数来判断 Java代码实现: 1 public class ReverseInteger { 2 public static int reverseInt(int x){ 3 if (x == 0) { 4 return

反转二叉树

输入一个二叉树,输出其镜像. 如下图,即交换所有节点的左右子树. 这里提供两种思路:使用递归和不使用递归. 使用的二叉树定义如下: public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } } 解决方法: import java.util.LinkedList; import java.util.Sca

配置SSH环境详细步骤+反转项目

反转项目+SSH详细配置过程(每步截图) 一.创建DataSource 1.配置连接数据库的一些基本动作 2.注意:选择第三项,然后点击Add 点击Add后出现如下图,选择你要导入的数据库 3.Finished 二.新建Web Project 注意:Target runtime 选这个,而不是Tomcat 7.0 三.添加struts能力 1注意Target. Runtime的选择 2.此处注意选择spring plugin 四.添加spring能力 1.注意Target runtime的选择:

使用CSS3滤镜让图片反转颜色

CSS提供的滤镜也是一大亮点,我一直痴迷其中,有些滤镜的效果很有用,可是有些的滤镜效果可能只是为了玩玩儿,CSS常见的滤镜有这些:grayscale, blur, sepia,所有常见的过滤器.但是如何使用和转化图片呢?今天我们主要是来讲讲如何使用CSS3滤镜让图片反转颜色. CSS代码 invert滤镜就是为了设置元素的反色效果,他的值设置范围为:0-100%,100%为完全反色,0为显示正常的颜色. .normal {     filter: invert(0%); } .inverted