标签:偶数 代码 mini efi 输入 using single his out
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 51056 | Accepted: 21551 |
Description
Input
Output
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 }
标签:偶数 代码 mini efi 输入 using single his out
原文地址:https://www.cnblogs.com/tuyang1129/p/9277303.html