状压dp
Posted hzoidj123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了状压dp相关的知识,希望对你有一定的参考价值。
翻转游戏
题目大意:翻转游戏是在一个 的正方形上进行的,在正方形的 个格上每个格子都放着一个双面的物件。每个物件的两个面,一面是白色,另一面是黑色,每个物件要么白色朝上,要么黑色朝上,每次你只能翻一个物件,从而由黑到白的改变这些物件上面的颜色,反之亦然。每一轮被选择翻转的物件遵循以下规则:
- 从16个物件中任选一个
- .翻转所选择的物件的同时,所有与它相邻的左方物件、右方物件、上方物件和下方物件(如果有的话),都要跟着翻转。
以下为例:
bwbw
wwww
bbwb
bwwb
这里b表示该格子放的物件黑色面朝上w 表示该格子放的物件白色朝上。如果我们选择翻转第三行的第一个物件,那么格子状态将变为:
bwbw
bwww
wwwb
wwwb
游戏的目标是翻转到所有的物件白色朝上或黑色朝上。你的任务就是写一个程序来求最少的翻转次数来实现这一目标。
输入格式
输入文件包含4 行,每行4 个字符,每个字符w或b表示游戏开始时格子上物件的状态。
输出格式
输出文件仅一个整数,即从给定状态到实现这一任务的最少翻转次数。如果给定的状态就已经实现了目标就输出 0,如果不可能实现目标就输出:Impossible 。
样例输入
bwwb
bbwb
bwwb
bwww
样例输出
4
思路:因为数据范围太小所以直接暴力即可:先确定第一行状态之后第二行也就确定了(因为一个反转时连带着上下左右一起翻转),依次类推
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 using namespace std; 5 const int inf=0x3f3f3f3f; 6 char s[6][6]; 7 char tem[6][6]; 8 int ans=inf,sum=0; 9 void work(char &ch){//!取地址,不然相当与没 10 if(ch==‘w‘) ch=‘b‘; 11 else if(ch==‘b‘) ch=‘w‘;//不能直接写else 12 } 13 void pre(int i,int j){ 14 sum++; 15 work(tem[i][j]); 16 work(tem[i-1][j]); 17 work(tem[i+1][j]); 18 work(tem[i][j-1]); 19 work(tem[i][j+1]); 20 } 21 void cl(int x,char ch){ 22 memcpy(tem,s,sizeof(s)); 23 sum=0;//因为要用两次注意归0 24 for(int i=1;i<=4;i++){ 25 if(x&1<<(i-1)) pre(1,i); 26 } 27 for(int i=2;i<=4;i++){ 28 for(int j=1;j<=4;j++){ 29 if(tem[i-1][j]!=ch){//因为是一行一行推,若上一行不是‘ch’,交换 30 pre(i,j); 31 } 32 } 33 } 34 for(int i=1;i<=4;i++){ 35 if(tem[4][i]!=ch){ 36 return; 37 } 38 }//若最后一行不符合return 39 ans=min(ans,sum); 40 } 41 int main(){ 42 for(int i=1;i<=4;i++) scanf("%s",s[i]+1); 43 for(int i=0;i<15;i++){//枚举第一行状态(翻或不翻) 44 cl(i,‘w‘); 45 cl(i,‘b‘); 46 } 47 if(ans==inf) printf("Impossible "); 48 else printf("%d ",ans); 49 return 0; 50 }
以上是关于状压dp的主要内容,如果未能解决你的问题,请参考以下文章