• 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
    ", min_flip);
    	}
    	return 0;
    }
    
  • 相关阅读:
    iOS崩溃治理--基础设施篇
    iOS崩溃治理--开篇
    AFNetworking 源码解读
    NSURLSession使用, 后台下载
    iOS10 越狱, openSSH
    iOS 私有API调用
    IOS 中openGL使用(使用基准图快速制作滤镜)
    IOS 中openGL使用教程4(openGL ES 入门篇 | 离屏渲染)
    IOS 中openGL使用教程3(openGL ES 入门篇 | 纹理贴图(texture)使用)
    SSM整合配置文件的主要内容
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/4908587.html
Copyright © 2020-2023  润新知