poj—1753 (DFS+枚举)

Flip Game

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 51056   Accepted: 21551

Description

Flip game is played on a rectangular 4x4 field with two-sided pieces placed on each of its 16 squares. One side of each piece is white and the other one is black and each piece is lying either it‘s black or white side up. Each round you flip 3 to 5 pieces, thus changing the color of their upper side from black to white and vice versa. The pieces to be flipped are chosen every round according to the following rules:

  1. Choose any one of the 16 pieces.
  2. Flip the chosen piece and also all adjacent pieces to the left, to the right, to the top, and to the bottom of the chosen piece (if there are any).

Consider the following position as an example:

bwbw 
wwww 
bbwb 
bwwb 
Here "b" denotes pieces lying their black side up and "w" denotes pieces lying their white side up. If we choose to flip the 1st piece from the 3rd row (this choice is shown at the picture), then the field will become:

bwbw 
bwww 
wwwb 
wwwb 
The goal of the game is to flip either all pieces white side up or all pieces black side up. You are to write a program that will search for the minimum number of rounds needed to achieve this goal.

Input

The input consists of 4 lines with 4 characters "w" or "b" each that denote game field position.

Output

Write to the output file a single integer number - the minimum number of rounds needed to achieve the goal of the game from the given position. If the goal is initially achieved, then write 0. If it‘s impossible to achieve the goal, then write the word "Impossible" (without quotes).

Sample Input

bwwb
bbwb
bwwb
bwww

Sample Output

4

题意:给了你一个4*4的棋盘,棋盘上的每一个格子里都有一颗一面黑一面白的棋子,一开始给出你棋盘的初始状态,你可以给任何一个棋子翻面,但是如果你翻了某一个棋子,那他上下左右的棋子都要翻面。问你最少需要翻多少次才能让16枚棋子都为黑或都为白。思路:总共有16个棋子,每个棋子只有两种状态,翻或者不翻,因为一面棋子只有两种颜色,翻基数次等同于只翻了1次,翻偶数次等同于没翻。所以可以分别枚举翻1枚,2枚,3枚,4枚......16枚的所有情况。根据排列组合,枚举完所有情况需要2^16次。那如何进行枚举呢?可以用for循环一 一枚举某一次需要翻的棋子数,然后用DFS搜索翻这个数量的棋子的所有情况。如何DFS呢?首先选择要翻的第一个棋子,然后下一个要翻的棋子从已选择的这个棋子之后进行选择,一直到选完需要数量的棋子,然后判断所有棋子是否为同一种颜色,如果是,则不用再进行搜索了,这就是答案,因为你是从1-16依次枚举,所以第一次满足条件的情况一定是次数最少的;如果不是则继续搜索。具体看代码和注释理解:
 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<string>
 6 #include<algorithm>
 7 #include<stack>
 8 #include<queue>
 9 #define ll long long
10 #define inf 0x3f3f3f3f
11 using namespace std;
12
13 int visit[20];
14 int map[7][7];
15 int ans;
16
17 void Flip()
18 {
19     int x,y;
20     for(int i=1; i<=16; ++i)
21     {
22         if(visit[i]) //如果标记为 1,表示这个棋子要翻
23         {
24             x = i/4 + 1; // 计算出棋子再棋盘中的位置
25             y = i % 4;
26             if(i%4 == 0)
27             {
28                 x--;
29                 y = 4;
30             }
31             map[x][y] = -map[x][y]; //翻自己
32             map[x-1][y] = -map[x-1][y]; //翻上
33             map[x+1][y] = -map[x+1][y]; //翻下
34             map[x][y+1] = -map[x][y+1]; //翻左
35             map[x][y-1] = -map[x][y-1]; //翻右
36         }
37     }
38     return;
39 }
40
41 int Judge() //判断是否为同一种颜色
42 {
43     for(int i=1; i<=4; ++i)
44         for(int j=1; j<=4; ++j)
45         {
46             if(map[i][j] != map[1][1])
47                 return 0;
48         }
49     return 1;
50 }
51
52 void DFS(int num,int times,int who) //num表示总共要翻几个琪,times表示已经翻了几个,who表示上一次翻的是哪一个棋
53 {
54     if(ans < inf) return; //如果已经找到答案了,就不用往下了
55     if(times == num) //当翻棋的数量达到了,就进行判断
56     {
57         Flip(); //翻棋
58         if(Judge()) //判断全为同一种颜色
59         {
60             ans = num;    //记录答案
61         }
62         else Flip(); //否则将棋盘恢复原状
63         return;
64     }
65
66     for(int i=who+1; i<=16; ++i) //从上一个翻的棋子的下一个开始选择,这样可以防止出现重复的情况
67     {
68         visit[i] = 1;//选中的标记为 1
69         DFS(num,times+1,i); //搜索翻下一个的情况,
70         visit[i] = 0; //清除标记
71     }
72 }
73
74 int main()
75 {
76     char first;
77     memset(map,0,sizeof(map));
78     for(int i=1; i<=4; ++i)
79     for(int j=1; j<=4; ++j)
80     {
81         cin>>first;//依次输入棋子
82         if(first == ‘w‘)
83             map[i][j] = 1; //若为白棋,记为 1
84         else map[i][j] = -1; //黑记为为 -1
85     }
86
87     ans = inf; //初始化答案为无穷大
88     for(int i=0; i<=16; ++i) //枚举翻棋子数
89     {
90         memset(visit,0,sizeof(visit)); //每种情况开始前要将标记数组初始化为 0
91         DFS(i,0,0); //搜索翻这么多棋子的所有情况
92         if(ans < inf) break; //如果答案不为无穷大,表示已经有结果了,不用搜了
93     }
94
95     if(ans == inf) cout<<"Impossible"<<endl;
96     else cout<<ans<<endl;
97     return 0;
98 }
 

原文地址:https://www.cnblogs.com/tuyang1129/p/9277303.html

时间: 2024-10-12 13:59:58

poj—1753 (DFS+枚举)的相关文章

poj 1753 flip[ 枚举 ]

传送门:http://poj.org/problem?id=1753 思路:16格用16位的int表示,然后用bfs的层次关系枚举: 代码: #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<queue> #include<stack> #include<map> #de

Flip Game (poj 1753)枚举+二进制

Flip Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 31031   Accepted: 13500 Description Flip game is played on a rectangular 4x4 field with two-sided pieces placed on each of its 16 squares. One side of each piece is white and the

poj 1562 DFS+枚举

Oil Deposits Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 14611   Accepted: 7961 Description The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSurvComp works with one large rectangular r

POJ 1753 Flip Game(dfs+枚举)

POJ 1753 题意: 输入一个4*4的图像,由黑白两色组成,定义一种操作为:改变某个格子内小球的颜色(黑变白,白变黑),同时其上下左右的格子内小球也将变色.求最少多少次操作能使之成为纯色图案. 思路: 对一个格子操作偶数次等于没有操作,操作奇数次等于操作一次,所以答案在0~16以及impossible之间. 从n=0开始枚举n次操作可能的组成情况,即操作哪几个格子,若某种组合能变图案为纯色则停止. 由于总组合数达到2^16,故枚举组合情况可以用dfs来进行回溯枚举. //还有一种方法是位运算

POJ 1753 Flip Game (DFS + 枚举)

题目:http://poj.org/problem?id=1753 这个题在开始接触的训练计划的时候做过,当时用的是DFS遍历,其机制就是把每个棋子翻一遍,然后顺利的过了,所以也就没有深究. 省赛前一次做PC2遇到了几乎一模一样的题,只不过是把棋盘的界限由4X4改为了5X5,然后一直跑不出结果来,但是当时崔老湿那个队过了,在最后总结的时候,崔老湿就说和这个题一样,不过要枚举第一行进行优化. 我以为就是恢复第一行然后第二行以此类推,不过手推一下结果是6不是4,就知道这个有问题. 问了崔老湿,问了+

poj 1753 Flip Game(bfs状态压缩 或 dfs枚举)

Description Flip game is played on a rectangular 4x4 field with two-sided pieces placed on each of its 16 squares. One side of each piece is white and the other one is black and each piece is lying either it's black or white side up. Each round you f

poj 2965 The Pilots Brothers&#39; refrigerator(dfs 枚举 +打印路径)

链接:poj 2965 题意:给定一个4*4矩阵状态,代表门的16个把手,'+'代表关,'-'代表开,当16个把手都为开(即'-')时,门才能打开,问至少要几步门才能打开 改变状态规则:选定16个把手中的任意一个,可以改变其本身以及同行同列的状态(即若为开,则变为关,若为关,则变为开),这一次操作为一步. 分析:这题与poj 1753思路差不多,每个把手最多改变一次状态, 所有整个矩阵最多改变16次状态 思路:直接dfs枚举所有状态,直到找到目标状态 但是要打印路径,所有应在dfs时记录路径 注

poj 1753 Flip Game (bfs + 枚举)

链接:poj 1753 题意:这是翻棋游戏,给定4*4棋盘,棋子一面为黑色(用b表示),另一面为白色(用w表示),问至少要几步可以将棋子翻为全黑或者全白,如不能达到目的,输出"Impossible " 翻转规则:可以选定16个棋子中的任意一个,将其本身以及上下左右相邻的翻转过来 分析:其实每格棋子最多只可以翻转一次(实际是奇数次,但与翻转一次状态一样),只要其中一格重复翻了2次(不论是连续翻动还是不连翻动),那么它以及周边的棋子和没翻动时的状态是一致的,与最初状态未翻转一样,由此就可以

[ACM训练] 算法初级 之 基本算法 之 枚举(POJ 1753+2965)

先列出题目: 1.POJ 1753 POJ 1753  Flip Game:http://poj.org/problem?id=1753 Sample Input bwwb bbwb bwwb bwww Sample Output 4 入手竟然没有思路,感觉有很多很多种情况需要考虑,也只能使用枚举方法才能解决了吧~ 4x4的数组来进行数据存储的话操作起来肯定非常不方便,这里借用位压缩的方法来存储状态,使用移位来标识每一个位置的的上下左右的位置操作. 详细看这里. 1.当棋盘状态id为0(全白)或