翻硬幣 搜尋

2021-07-29 13:59:33 字數 1366 閱讀 6585

有乙個n*m的格仔,每個格仔上有乙個硬幣,用0表示正面朝上,1表示反面朝上。

一次操作你可以將一行或一列的硬幣都反轉,問你是否能夠進行一系列的操作之後使得所有的硬幣都朝上。

這道題和黑白棋那道類似,黑白棋那道有個啟發式資訊是乙個點不會反轉超過一次,這道題也是同樣的道理,一行或一列不會反轉超過一次。

然後我們觀察一種可能的反轉情況:

我們可以發現這樣的資訊:反轉的情況類似於「井」狀,並且出於交叉出的點一定是0,因為只有0點在反轉兩次後才會依然朝上。

繼續觀察我們發現了一條有用的資訊:

一種可行的反轉操作集合的補集也一定是可行的,如下圖:

這樣,我們不妨將第一行反轉,對於第一行中為0的點我們將這些點所在的列也反轉,做了這樣乙個初始操作之後我們繼續看後面的行,後面不可能在進行列反轉操作了,因為這會破壞第一行的狀態,所以我們只需要去統計後面每一行是否都是相同的數就行了。

還有需要注意的一點就是題目中給的圖範圍是n*m<106

但並沒有給n和m的範圍,所以我們需要用一維陣列去模擬二維陣列,mat[x][y]用a[i]表示,其中i=(x-1)*m+y

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

const

long

long

int inf=0x7fffffffffffffff;

const

int maxn= 1000005;

int a[maxn];

int t;

int n,m;

bool x_change[maxn];//x_change[i]為1表示第i行反轉,0表示不反轉

bool y_change[maxn];

void init()

bool work()

int cnt;//

for(int i=1;i<=n;i++)//n行m列

if(cnt>0 && cntreturn

0; }

return1;}

int main()

}if(work()==1)printf("yes\n");

else

printf("no\n");

}return

0;}

翻硬幣問題

翻硬幣問題 翻硬幣問題有好幾種。其中的一種是這樣的 桌子上有q m n枚硬幣,m正面朝上,n枚反面朝上,每一輪翻p枚,在每一輪翻幣的時候,被翻的同一枚硬幣只能翻一次。問最少多少次能把所有的硬幣翻成全部正面或者反面朝上?根據問題的描述,問題實際上隱含 m n p 0,m n p。這個問題往往是計算機程...

翻硬幣(貪心)

歷屆試題 翻硬幣 時間限制 1.0s 記憶體限制 256.0mb 問題描述 小明正在玩乙個 翻硬幣 的遊戲。桌上放著排成一排的若干硬幣。我們用 表示正面,用 o 表示反面 是小寫字母,不是零 比如,可能情形是 oo oooo 如果同時翻轉左邊的兩個硬幣,則變為 oooo oooo 現在小明的問題是 ...

矇眼翻硬幣

有四個硬幣,正反面隨機地放在正方形的四個角,像這樣 正 反 正 反蒙著眼,每次可以同時翻兩個,請設計乙個策略,使得4個硬幣最後是同一面朝上。其實初始情況只有三種。正 反 反 正正 正 反 反正 正 正 反正 反 反 反 反 正 反 反2.1 正 正 正 反 反 反 正 反或者 2.2正 反 反 反 ...