编程题-翻棋游戏-枚举

题目

 约翰知道,那些高智力又快乐的奶牛产奶量特别高.所以他做了一个翻瓦片的益智游戏来娱乐奶牛.在一个M×N(1≤M,N≤15)的骨架上,每一个格子里都有一个可以翻转的瓦片.瓦片的一面是黑色的,而另一面是白色的.对一个瓦片进行翻转,可以使黑变白,也可以使白变黑.然而,奶牛们的蹄子是如此的巨大而且笨拙,所以她们翻转一个瓦片的时候,与之有公共边的相邻瓦片也都被翻转了.那么,这些奶牛们最少需要多少次翻转,使所有的瓦片都变成白面向上呢?如杲可以做到,输出字典序最小的结果(将结果当成字符串处理).如果不能做到,输出“IMPOSSIBLE”.

样例

输入

M=4

N=4

每个格子的颜色如下(0表示白色,1表示黑色)

1 0 0 1

0 1 1 0

0 1 1 0

1 0 0 1

输出:

0 0 0 0

1 0 0 1

1 0 0 1

0 0 0 0

题目分析

首先,一个格子的连续翻转2次的,颜色会恢复原状,并且一个格子的颜色变换取决于他周围和他自身,那么可以知道,

1.一个棋子要么翻或者不翻,不会存在一个棋子翻2次及其以上

2.给定一个解法,翻棋子的顺序是无关紧要的

如果我们用枚举的方法,枚举出每一行的翻法,复杂度为O(2MN)。

但是我们发现,只要枚举出第一行的所有翻法,那么第二行的翻法是确定的(就是保证第一行的中所有是黑色的格子,则必须翻转对应的下一行格子(如果这样,那么第一行就不能满足条件)

这样,给出了前一行的翻法,那么他一下行的翻法也就固定了,这样只要判断最后一行是否全是白色,就可以判断这个解法是不是正确的,这样的话,复杂度就降低为O(MN2N)

python代码

已样例作为输入

我们输出了所有的解法,已验证我们算法是不是正确的,并在最后打印最优解

import copy

#m*n
a=[
   [1,0,0,1],
   [0,1,1,0],
   [0,1,1,0],
   [1,0,0,1]
   ]

m=4
n=4
#保存最小步数以及对应到解
m_step=m*n
min_solve=list()

#打印一个解
def print_solve(ans):
    for i in ans:
        print i
    print ‘------------------------‘

#对于第一行到翻转方法,有没有对应到解,
#x到位代表当前到第一行到翻法
#比如x=5 2进制表示为(只取最后4位) .... 0101  1在到位置表示要翻,这里意思是翻第二个和第四个
#(注意:程序由于方便,其实是把2进制到顺序反向排列到,比如上面,其实反序后是 1010 ....表示翻第一个和第三个)
def check(x):
    tmp=copy.deepcopy(a)
    ans=[[0]*n for t in range(m)]
    step=0;
    for i in range(m):
        if x & 1<<i:
            ans[0][i]=1
            step+=1
            #翻转自身和周围
            tmp[0][i]^=1
            if m > 1:
                tmp[1][i]^=1
            if i>0:
                tmp[0][i-1]^=1
            if i<n-1:
                tmp[0][i+1]^=1
    for i in range(1,m):
        for j in range(0,n):
            if tmp[i-1][j]==1:
                ans[i][j]=1
                step+=1
                #翻转自身和周围
                tmp[i-1][j]^=1
                tmp[i][j]^=1
                if i < m-1:
                    tmp[i+1][j]^=1
                if j>0:
                    tmp[i][j-1]^=1
                if j<n-1:
                    tmp[i][j+1]^=1
    #如果最后一行存在1,则表示当前第一行到翻法是无解
    for i in range(n):
        if tmp[m-1][i]==1:
            return False

    print_solve(ans)
    global m_step,min_solve
    if m_step > step:
        m_step=step
        min_solve=ans
    return True

solve_num=0;
for x in range(1<<n):
    if check(x):
        solve_num+=1

if solve_num==0:
    print "impossible"
else:
    print "min step is %d" % m_step
    print_solve(min_solve)

输出:

[0, 0, 0, 0]
[1, 0, 0, 1]
[1, 0, 0, 1]
[0, 0, 0, 0]
------------------------
[1, 0, 0, 0]
[0, 1, 0, 1]
[0, 0, 1, 1]
[0, 1, 1, 1]
------------------------
[0, 1, 0, 0]
[0, 1, 1, 1]
[1, 0, 0, 0]
[1, 1, 0, 1]
------------------------
[1, 1, 0, 0]
[1, 0, 1, 1]
[0, 0, 1, 0]
[1, 0, 1, 0]
------------------------
[0, 0, 1, 0]
[1, 1, 1, 0]
[0, 0, 0, 1]
[1, 0, 1, 1]
------------------------
[1, 0, 1, 0]
[0, 0, 1, 0]
[1, 0, 1, 1]
[1, 1, 0, 0]
------------------------
[0, 1, 1, 0]
[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 1, 1, 0]
------------------------
[1, 1, 1, 0]
[1, 1, 0, 0]
[1, 0, 1, 0]
[0, 0, 0, 1]
------------------------
[0, 0, 0, 1]
[1, 0, 1, 0]
[1, 1, 0, 0]
[1, 1, 1, 0]
------------------------
[1, 0, 0, 1]
[0, 1, 1, 0]
[0, 1, 1, 0]
[1, 0, 0, 1]
------------------------
[0, 1, 0, 1]
[0, 1, 0, 0]
[1, 1, 0, 1]
[0, 0, 1, 1]
------------------------
[1, 1, 0, 1]
[1, 0, 0, 0]
[0, 1, 1, 1]
[0, 1, 0, 0]
------------------------
[0, 0, 1, 1]
[1, 1, 0, 1]
[0, 1, 0, 0]
[0, 1, 0, 1]
------------------------
[1, 0, 1, 1]
[0, 0, 0, 1]
[1, 1, 1, 0]
[0, 0, 1, 0]
------------------------
[0, 1, 1, 1]
[0, 0, 1, 1]
[0, 1, 0, 1]
[1, 0, 0, 0]
------------------------
1
[1, 1, 1, 1]
[1, 1, 1, 1]
[1, 1, 1, 1]
[1, 1, 1, 1]
------------------------
min step is 4
[0, 0, 0, 0]
[1, 0, 0, 1]
[1, 0, 0, 1]
[0, 0, 0, 0]
------------------------
时间: 2024-11-09 02:26:49

编程题-翻棋游戏-枚举的相关文章

YTU 2845: 编程题AB-卡片游戏 dfsA

2845: 编程题AB-卡片游戏 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 19  Solved: 9 [Submit][Status][Web Board] Description 小明对数字的序列产生了兴趣: 现有许多张不同的数字卡片,用这若干张卡片能排列出很多序列,要求算出这若干张不同卡片的全排列总数,并按从小到大的顺序输出这些序列. Input 输入数字n,表示输入数字序列个数,接着输入n个不同的数字,代表n张卡片上的数字(0<=数字

[编程题-蘑菇街] 投篮游戏

有一个投篮游戏.球场有p个篮筐,编号为0,1...,p-1.每个篮筐下有个袋子,每个袋子最多装一个篮球.有n个篮球,每个球编号xi .规则是将数字为xi 的篮球投到xi 除p的余数为编号的袋里.若袋里已有篮球则球弹出游戏结束输出i,否则重复至所有球都投完.输出-1.问游戏最终的输出是什么? 输入描述: 第一行两个整数p,n(2≤p,n≤300).p为篮筐数,n为篮球数.接着n行为篮球上的数字xi(0≤xi≤1e9) 输出描述: 输出游戏的结果 输入例子: 10 5021534153 输出例子:

编程题:为枚举类型变量赋值。将整型值强制类型转换成枚举类型赋值

编程题:为枚举类型变量赋值.将整型值强制类型转换成枚举类型赋值 #include<stdio.h> void main() { enum season {spring,summer,autumn,winter}s1,s2; s1=summer; s2=(enum season)2; printf("s1=%d,s2=%d\n",s1,s2); } 编程题:为枚举类型变量赋值.将整型值强制类型转换成枚举类型赋值,布布扣,bubuko.com

编程题:枚举元素的判断比较,功能:枚举变量作为循环控制变量

#include<stdio.h> void main() {  enum season {spring=1,summer,autumn,winter}s; for(s=spring;s<=winter;s++) printf("%d\n",s); } 编程题:枚举元素的判断比较,功能:枚举变量作为循环控制变量,布布扣,bubuko.com

POJ C程序设计进阶 编程题#3 : 排队游戏

编程题#3:排队游戏 来源: POJ (Coursera声明:在POJ上完成的习题将不会计入Coursera的最后成绩.) 注意: 总时间限制: 1000ms 内存限制: 65536kB 描述 在幼儿园中,老师安排小朋友做一个排队的游戏.首先老师精心的把数目相同的小男孩和小女孩编排在一个队列中,每个小孩按其在队列中的位置发给一个编号(编 号从0开始).然后老师告诉小朋友们,站在前边的小男孩可以和他后边相邻的小女孩手拉手离开队列,剩余的小朋友重新站拢,再按前后相邻的小男孩小女孩手拉 手离开队列游戏

1647: [Usaco2007 Open]Fliptile 翻格子游戏

1647: [Usaco2007 Open]Fliptile 翻格子游戏 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 423  Solved: 173[Submit][Status][Discuss] Description Farmer John knows that an intellectually satisfied cow is a happy cow who will give more milk. He has arranged a

网易2017春招笔试真题编程题集合题解

01 双核处理 题目 一种双核CPU的两个核能够同时的处理任务,现在有n个已知数据量的任务需要交给CPU处理,假设已知CPU的每个核1秒可以处理1kb,每个核同时只能处理一项任务.n个任务可以按照任意顺序放入CPU进行处理,现在需要设计一个方案让CPU处理完这批任务所需的时间最少,求这个最小的时间. 输入描述 输入包括两行:第一行为整数n(1 ≤ n ≤ 50)第二行为n个整数lengthi,表示每个任务的长度为length[i]kb,每个数均为1024的倍数. 输出描述输出一个整数,表示最少需

搜狐2016研发工程师编程题

1.[编程题]马戏团 搜狐员工小王最近利用假期在外地旅游,在某个小镇碰到一个马戏团表演,精彩的表演结束后发现团长正和大伙在帐篷前激烈讨论,小王打听了下了解到, 马戏团正打算出一个新节目“最高罗汉塔”,即马戏团员叠罗汉表演.考虑到安全因素,要求叠罗汉过程中,站在某个人肩上的人应该既比自己矮又比自己瘦,或相等. 团长想要本次节目中的罗汉塔叠的最高,由于人数众多,正在头疼如何安排人员的问题.小王觉得这个问题很简单,于是统计了参与最高罗汉塔表演的所有团员的身高体重,并且很快找到叠最高罗汉塔的人员序列.

美团点评2017秋招笔试编程题

美团点评2017秋招笔试编程题 1, 大富翁游戏,玩家根据骰子的点数决定走的步数,即骰子点数为1时可以走一步,点数为2时可以走两步,点数为n时可以走n步.求玩家走到第n步(n<=骰子最大点数且是方法的唯一入参)时,总共有多少种投骰子的方法. 题解: 写出前面的几个, 1 -> 1;   2 -> 2 ;  3 -> 4;   4 -> 8; 5 -> 16; 6 -> 32; 可以得到是 二的 n-1 次幂. #include <cstdio> int