AcWing 飛行員兄弟

2022-06-25 01:48:09 字數 1881 閱讀 7292

資料範圍非常 小,可以列舉出所有的操作尋找最優解.

如何列舉所有的操作?首先看出來這個問題有這樣的性質:

①如果改變了乙個把手的狀態,那麼就沒有必要再次改變它.

②改變多個把手狀態的順序對結果沒有影響.

所以,所有的操作即為最終對於每把手進行狀態切換或者不進行狀態切換,也就是選或者不選的問題.

共有16個把手,所以共有216種操作方法.現在需要列舉這些操作方法.

在此之前先來看看怎麼表示所有把手的狀態.

首先把所有把手放到一行來觀察,如本題樣例變為:

-+-----------+--
用0表示閉合,1表示開啟,則可以將這個初始狀態表示為:

0100 0000 0000 0100
這可以看作乙個用二進位制表示的數字,且這個數字是該二進位制表示方法唯一表示的,他們是一一對映關係.

那麼就可以用二進位制下的:

0000 0000 0000 0000 到 1111 1111 1111 1111

來表示所有可能的狀態.在十進位制下這個區間等價為0 ~ 65535,這個區間裡的每乙個數都代表了乙個狀態.

現在就知道表示這些狀態的方法了.

現在要根據這些狀態進行操作,為了體現把手原本的座標有如下實現:

// 這裡的t即為儲存狀態的數字

for(int i = 1; i <= 4; i++)

for(int j = 1; j <= 4; j++)

到此,就可以將某個狀態壓縮為乙個數字並對其進行讀取和需要的處理.

但實際上這題更方便的做法是用陣列儲存把手狀態,而對把手的操作壓縮一下.

現在需要列舉所有的操作,根據上文提到的,如果用0表示不改變其狀態,用1表示改變其狀態,同樣可以用二進位制下的:

0000 0000 0000 0000 到 1111 1111 1111 1111

來表示.並且有類似地方法來讀取每乙個座標上的操作.

有如下實現:

// x 即為儲存16個把手操作方法的數字

// tmp 對應輸入的原始把手狀態,這裡用bool陣列表示更方便

for(int i = 1; i <= 4 && x; i++)

for(int j = 1; j <= 4 && x; j++)

x >>= 1;

}

最後,題目要求輸出進行操作的點的座標,運用位操作+列舉座標也可以輕鬆做到.

ac code:

#include #include #include #include using namespacestd;

bool s[5][5], tmp[5][5];

int ans = (1 << 16) - 1, ct;

bool check(intx)

x >>= 1;

}for(int i = 1; i <= 4; i++)

for(int j = 1; j <= 4; j++)

if(!tmp[i][j]) return false;

return true;

}void cmp(intx)

while(t2)

if(ct1 > ct2) ans =x;

}intmain()

for(int i = 0; i <= (1 << 16) - 1; i++)

int t =ans;

while(t)

printf("%d\n", ct);

for(int i = 1; i <= 4; i++)

for(int j = 1; j <= 4; j++)

return 0;

}

Acwing 116 飛行員兄弟

飛行員兄弟 這個遊戲,需要玩家順利的開啟乙個擁有16個把手的冰箱。已知每個把手可以處於以下兩種狀態之一 開啟或關閉。只有當所有把手都開啟時,冰箱才會開啟。把手可以表示為乙個4 4的矩陣,您可以改變任何乙個位置 i,j 上把手的狀態。但是,這也會使得第i行和第j列上的所有把手的狀態也隨著改變。請你求出...

飛行員兄弟

飛行員兄弟 這個遊戲,需要玩家順利的開啟乙個擁有16個把手的冰箱。已知每個把手可以處於以下兩種狀態之一 開啟或關閉。只有當所有把手都開啟時,冰箱才會開啟。把手可以表示為乙個4 4的矩陣,您可以改變任何乙個位置 i,j 上把手的狀態。但是,這也會使得第i行和第j列上的所有把手的狀態也隨著改變。請你求出...

飛行員兄弟

飛行員兄弟 這個遊戲,需要玩家順利的開啟乙個擁有16個把手的冰箱。已知每個把手可以處於以下兩種狀態之一 開啟或關閉。只有當所有把手都開啟時,冰箱才會開啟。把手可以表示為乙個4 4的矩陣,您可以改變任何乙個位置 i,j 上把手的狀態。但是,這也會使得第i行和第j列上的所有把手的狀態也隨著改變。請你求出...