Fliptile POJ - 3279 (翻转)(二进制+对第一行暴力遍历翻转的位置)
題意:給你一個給你一個矩陣,有黑白兩個狀態。每次你可以選擇一個變為其相反的狀態,它周圍的4個都會變成相反的狀態。問你最少需要改變多少個使得矩陣中的狀態全為白色,若有多個答案,輸出字典序最小的
思路:白書p153
題解:這個題仍然是個反轉問題,我們只需要枚舉第一行(二進制)進行翻轉的坐標, 然后根據當前這塊上面那塊是否是黑色(依據該塊上面本來是什么以及周圍或者自身總共反轉了多少次確定)最后得出該塊是否需要反轉, 最后只需要特判最后一行是否合理即全為白色,并進行維護更新答案即可。
另外其實每個點最多只會被翻轉一次,因為如果翻轉兩次和不翻轉是一樣的。
Farmer John knows that an intellectually satisfied cow is a happy cow who will give more milk. He has arranged a brainy activity for cows in which they manipulate an?M?×?N?grid (1 ≤?M≤ 15; 1 ≤?N?≤ 15) of square tiles, each of which is colored black on one side and white on the other side.
As one would guess, when a single white tile is flipped, it changes to black; when a single black tile is flipped, it changes to white. The cows are rewarded when they flip the tiles so that each tile has the white side face up. However, the cows have rather large hooves and when they try to flip a certain tile, they also flip all the adjacent tiles (tiles that share a full edge with the flipped tile). Since the flips are tiring, the cows want to minimize the number of flips they have to make.
Help the cows determine the minimum number of flips required, and the locations to flip to achieve that minimum. If there are multiple ways to achieve the task with the minimum amount of flips, return the one with the least lexicographical ordering in the output when considered as a string. If the task is impossible, print one line with the word "IMPOSSIBLE".
Input
Line 1: Two space-separated integers:?M?and?N?
Lines 2..?M+1: Line?i+1 describes the colors (left to right) of row i of the grid with?Nspace-separated integers which are 1 for black and 0 for white
Output
Lines 1..?M: Each line contains?N?space-separated integers, each specifying how many times to flip that particular location.
Sample Input
4 4 1 0 0 1 0 1 1 0 0 1 1 0 1 0 0 1Sample Output
0 0 0 0 1 0 0 1 1 0 0 1 0 0 0 0 #include<stdio.h> #include<string.h> using namespace std; const int M=110; int m,n; int mp[M][M]; int s[M][M];//保存中間結果 int w[M][M];///保存最優解,s,w,記錄的都是翻動操作 int e[5][2]= {0,0,0,1,1,0,-1,0,0,-1};//領接格子的坐標包括本身 int f(int x,int y)//查詢(x,y)的顏色判斷該點是否為黑色 {int xx=mp[x][y];for(int i=0; i<5; i++){int u=x+e[i][0],v=y+e[i][1];if(u>=0&&u<m&&v>=0&&v<n)xx+=s[u][v];}return xx%2; } int bfs()//求出第一行確定情況下的最小操作,不存在解的話,返回-1 {int ant=0;for(int i=1; i<m; i++)//求出從第二行開始翻轉for(int j=0; j<n; j++)//上方格子是黑色,必須必須反轉(i,j)號格子if(f(i-1,j))s[i][j]=1;for(int i=0; i<n; i++)//判斷最后一行是否全白if(f(m-1,i))return -1;for(int i=0; i<m; i++)//統計翻轉的次數for(int j=0; j<n; j++)ant+=s[i][j];return ant; } void solve() {int ans=0x3f3f3f3f;for(int i=0; i<(1<<n); i++)//按字典序嘗試第一行的所有可能性{memset(s,0,sizeof(s));for(int j=0; j<n; j++)//給第一行各個位置是否翻動按字典序賦值s[0][n-j-1]=i>>j&1;int num=bfs();if(num>=0&&ans>num){ans=num;memcpy(w,s,sizeof(s));//把dp數組復制給s數組(int數組的復制memcpy)}}if(ans==0x3f3f3f3f)printf("IMPOSSIBLE\n");else{for(int i=0; i<m; i++)///輸出翻動操作{for(int j=0; j<n-1; j++)printf("%d ",w[i][j]);printf("%d\n",w[i][n-1]);}} } int main() {while(~scanf("%d%d",&m,&n)){memset(w,0,sizeof(w));for(int i=0; i<m; i++)for(int j=0; j<n; j++)scanf("%d",&mp[i][j]);solve();}return 0; }?
總結
以上是生活随笔為你收集整理的Fliptile POJ - 3279 (翻转)(二进制+对第一行暴力遍历翻转的位置)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CAD打印图纸的拼接cad如何打印拼接图
- 下一篇: Jin Ge Jin Qu hao UV