題目大意:給乙個面,1代表黑色,0代表白色,翻乙個牌的同時,會把跟他有相鄰邊的牌一起翻了,問你如何才能在翻最少牌的情況下把他變成全白,如果有多種情況那麼輸出字典序最小的。
題目思路:對於一行來說,假如他有m個數,那麼很明顯,這一行一共有2^m種翻轉方案。所以我們很顯然的想出,可以用0~2^m-1的十進位制數,轉換成二進位制,來代表每一種翻轉方案。**中(i>>j)&1就是來將十進位制轉換成二進位制。然後對於每種翻轉情況,很清楚的可以看到,如果確定了第一行,那麼後面就能確定。因為第一行已經確定了,那麼為了把第一行的黑色變成白色,唯一的方案就是翻轉這個黑色塊下面的那個牌,所以我們要做的就是,從第二行開始,然後每個都判斷一下它上面的是不是黑色,如果是黑色,那麼就翻自己,temp[i][j]=1,這個temp是用來記錄翻轉的方案。那麼如何判斷上面是不是黑色呢?很簡單,簡單搜尋一下,這裡很巧妙的一種思路,首先是自己對應的顏色,+前後左右自己的翻轉次數,對2進行取模,如果是0就說明是白色,1就說明是黑色。全部解決完以後,判斷一下最後一行的顏色,如果最後一行全是白色的,那麼恭喜這個情況是可以的,如果最後一行存在黑塊,那麼只能涼涼了,因為沒有下一行能幫忙了。然後就是判斷一下這種情況下翻了幾次,如果翻得比當前ans存的小,那麼就把這個作為ans,複製到opt裡,opt作為最優解,由於我們是從0~2^m-1列舉翻轉情況,而且只有在num以下是**:
#include#include#include#includeusing namespace std;
#define inf 0x3f3f3f3f
#define maxn 20
#define rep(i,a,b) for(int i=a;i<=b;i++)
int n,m,map1[maxn][maxn],temp[maxn][maxn],opt[maxn][maxn];
int dir[5][2]=,,,,};
int judge(int x,int y)
}return temp2&1;
}int cal()}}
rep(i,1,m)
int num=0;
rep(i,1,n)
}return num;
}int main()
}int ans=inf,num;
rep(i,0,(1<>j)&1;
}num=cal();
if(num>=0&&num}
if(ans==inf)printf("impossible\n");
else}}
}return 0;
}
Poj 3279Fliptile 二進位制列舉)
題目傳送門 題意 給定0,1矩陣,每次反轉乙個位置,它相鄰的四個位置也會反轉 如果存在的話 反轉的意思就是1 0或者1 0,問最少反轉多少個位置就可以使矩陣全部變成0。最後輸出乙個矩陣,所有反轉的位置輸出1,否則輸出0,若存在多個答案相同,則輸出矩陣字典序最小的乙個。先從第一行開始反轉,利用二進位制...
二進位制列舉
fliptile 乙個反轉問題,大意是一頭牛要反轉木板,木板有黑和白,全部翻成白色的反法 輸出。小蒟蒻根本想不到 參考了大佬的部落格。點此轉入 把第一行的全部翻法都試一遍,然後看哪種的步數最少。好難想。include include int maze 20 20 int t 20 20 int f ...
二進位制列舉
一 二進位制操作 算數字運算 a 60 0011 1100 b 13 0000 1101 1.與 兩個二進位制數,同 1為 1,否則為 0。a b 12 0000 1100 2.或 兩個二進位制數,同 0為 0,否則為 1。a b 61 0011 1101 3.非 按位取反 對二進位制每一位進行了一...