1. 程式人生 > >【貪心列舉】撥鍾問題

【貪心列舉】撥鍾問題

問題描述
有9個時鐘,排成一個3*3的矩陣。現在需要用最少的移動,將9個時鐘的指標都撥到12點的位置。共允許有9種不同的移動。如右表所示,每個移動會將若干個時鐘的指標沿順時針方向撥動90度。

移動 影響的時鐘
1 ABDE
2 ABC
3 BCEF
4 ADG
5 BDEFH
6 CFI
7 DEGH
8 GHI
9 EFHI
輸入
從標準輸入裝置讀入9個整數,表示各時鐘指標的起始位置。0=12點、1=3點、2=6點、3=9點。
輸出
輸出一個最短的移動序列,使得9個時鐘的指標都指向12點。按照移動的序號大小,輸出結果。
樣例輸入
3 3 0
2 2 2
2 1 2
樣例輸出
4 5 8 9
解題思路:
假設時鐘指標位置對應的值為clock_time,那麼順時針旋轉90°就是clock_time = (clock_time+1)%4這一組時針就用一個數組表示。9種操作對應一個二維陣列。這一題實質類似熄燈問題和畫家問題。其共通點在於:操作對環境的改變是無序的,每個操作都會影響到周圍的狀態。同時每一種操作都有周期性限制,也即最多需要幾次操作,多於這個次數產生迴圈。熄燈問題中,每個燈最多熄燈一次,因為燈只有兩種狀態,並且迴圈。而這裡,有4種迴圈的狀態,因此每個移動操作頂多使用3次。我們對移動方法1,2,3進行列舉,每種方法無非實施0-3次,也即一共4^3=64種情況。這些情況之間並非沒有關係。例如,我們確定了1,2,3的情況數,那麼得到一個燈A,B,C的狀態,而只有移動4能夠改變A,移動5能夠改變B,移動6能夠改變C,那麼移動4-6的次數也確定了。同樣,這時只有移動7能夠改變D,移動9能夠改變F,這時移動7和9的次數也確定了。最後,時鐘A,B,C,D,F都已經到達12點,E,G,H,I還沒確定,只剩下移動8能夠改變GHI,所以只要檢查E是否已經到達12點以及,GHI的時鐘數是否相等就行了。最後找到一個移動次數最小的情況。
這題也可以用暴力搜尋,因為最多有4^9個組合,不會超時。
這題還可以列出一個方程組,九個未知數,通過高斯消元法來解方程組。
(一開始用列舉法寫了,至於上面的這種方法,稍後再補上吧)

程式碼:

#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
 int station[9] = {0};
 for (int i = 0; i < 9; i++)
  cin>>station[i];
 int move_count[9] = {0};
 int min_count = 10000;
 for (int i1 = 0; i1 < 4; i1++)
  for (int i2 = 0; i2 < 4; i2++)
   for (int i3 = 0; i3 < 4; i3++)
    for (int i4 = 0; i4 < 4; i4++)
     for (int i5 = 0; i5 < 4; i5++)
      for (int i6 = 0; i6 < 4; i6++)
       for (int i7 = 0; i7 < 4; i7++)
        for (int i8 = 0; i8 < 4; i8++)
         for (int i9 = 0; i9 < 4; i9++)
         {
          if ((0 == (i1 + i2 + i4 + station[0]) % 4) && (0 == (i1 + i2 + i3 + i5 + station[1])

              % 4) && (0 == (i2 + i3 + i6 + station[2]) % 4) && (0 == (i1 + i4 + i5 + i7 +

              station[3]) % 4) && (0 == (i1 + i3 + i5 + i7 + i9 + station[4]) % 4) && (0 ==

              (i3 + i5 + i6 + i9 + station[5])% 4) && (0 == (i4 + i7 + i8 + station[6]) % 4)

          && (0 == (i5 + i7 + i8 + i9 + station[7])% 4) && (0 == (i6 + i8 + i9 + station[8]) % 4))
          {
           int sum = i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9;
           if (min_count > sum)
           {
            min_count = sum;
            move_count[0] = i1;
            move_count[1] = i2;
            move_count[2] = i3;
            move_count[3] = i4;
            move_count[4] = i5;
            move_count[5] = i6;
            move_count[6] = i7;
            move_count[7] = i8;
            move_count[8] = i9;
           }
          }
         }
 int cur = 0;
 for (cur = 0; cur < 9; cur++)
  while (move_count[cur]--)
   cout<<cur + 1<<" ";
 cout<<endl;
 return 0;
}

相關推薦

貪心列舉問題

問題描述 有9個時鐘,排成一個3*3的矩陣。現在需要用最少的移動,將9個時鐘的指標都撥到12點的位置。共允許有9種不同的移動。如右表所示,每個移動會將若干個時鐘的指標沿順時針方向撥動90度。 移動 影響的時鐘 1 ABDE 2 ABC 3 BCEF 4 ADG 5 BD

codeforces #503 div 2 C Elections 貪心+列舉

題意: n個選民有對應的賄賂價格,最小要花費多少錢才能讓 編號1的選票是最多的; 思路: 貪心應該是比較容易想到的,但是如何列舉才能求出正確答案;這裡不是說把沒選編號1的選民都按照花費從小到大排序,然後從小到大依次加起來就完事了,我們還有一些特殊情況需要考慮的;比如

Fliptile構造+貪心列舉

題目連結   我們列舉第一列的答案,然後我們以此為基礎向下搜尋,題目要我們找的是‘1’數最少並且在‘1’數相等的時候,字典序最小的答案,直接按順序列舉即可。   給幾組測試樣例,過了這幾組,就是基本過了,一道構造題,卡了為好幾個小時…… #include

貪心策略渡河(river)

例子 整數 inpu tel assign roc con 題目 read “假舟楫者,非能水也,而絕江河。”這句話說的是,借助渡船的人,不是會遊水,卻能橫渡江河。 會遊水的人反而不一定能順利地橫渡江河。由於江面風浪很大,他們必須潛泳渡河。這就必須用到氧氣瓶。氧氣瓶

BZOJ1029JSOI2007建築搶修貪心+堆

namespace 一段 new -c iostream man mes mod priority Description 小剛在玩JSOI提供的一個稱之為“建築搶修”的電腦遊戲:經過了一場激烈的戰鬥,T部落消滅了全部z部落的入侵者。可是T部落的基地裏已經有N個建築設

bzoj 1572: [Usaco2009 Open]工作安排Job貪心+堆

貪心 open ret pan use 時間 algorithm ios 情況 先按照時間順序加,價值塞進小根堆裏,碰到不合法情況就從堆裏減去 #include<iostream> #include<cstdio> #include<queue

51nod-1065 最小正子段和 貪心 + 思維

記錄 n) 51nod nta cstring pla CA 找到 class N個整數組成的序列a[1],a[2],a[3],…,a[n],從中選出一個子序列(a[i],a[i+1],…a[j]),使這個子序列的和>0,並且這個和是所有和>0的

bzoj 1029: [JSOI2007]建築搶修貪心+堆

algo long tchar 不能 總數 建築 stream long long names 第一想法是按照結束時間貪心,但是這樣有反例 所以先按照t貪心,能選則選,把選的樓的持續時間放進大根堆裏,當當前的樓不能選的時候如果當前的持續時間比大根堆裏最大的要小,就用這個替換

非原創codeforces 1029F Multicolored Markers 貪心+構造

scanf 分享 ret ++ sed 遍歷 pen https int 題目:戳這裏 題意:給a個紅色小方塊和b個藍色小方塊,求其能組成的周長最小的矩形,要求紅色或藍色方塊至少有一個也是矩形。 思路來源:戳這裏 解題思路:遍歷大矩形可能滿足的所有周長,維護最小值即可。不易

bzoj 2151: 種樹貪心+堆

n) tchar put != clu prior 刪掉 printf emp 和數據備份差不多 設二元組(i,a[i]),開一個大根堆把二元組塞進去,以len排序,每次取出一個二元組 因為單純的貪心是不行的,所以設計一個“反悔”操作。 記錄二元組的前驅pr後繼ne,把拿出

貪心+排序排隊接水 luogu-1223

esp 貪心 人在 puts typedef getchar() 順序 getchar long 題目描述 有n個人在一個水龍頭前排隊接水,假如每個人接水的時間為Ti,請編程找出這n個人排隊的一種順序,使得n個人的平均等待時間最小。 分析 註意要開longlong AC代碼

20181027T2易水決貪心+堆

怎麽 init 下一個 turn ron prior first define int 原題:loj6035 【錯解】 全肝T1了沒怎麽想 【正解】 一眼貪心 先考慮\(b_i=0\)怎麽做 可以模擬一個正常人的思維 開一個堆,記錄每個任務需要的時間(包括等待),每次從中取

nssl1269-射擊貪心,堆

正題 題目大意 有n個東西,東西必須在 a i

POJ-1065 Wooden Sticks 貪心+標記

題目傳送門 題目:給你 N 個木棍,每根木棍都有一個長度 l 和一定重量 w 。機器每對一根進行操作需要一分鐘的時間 ,但是如果當前進行操作的木棍的長度和重量都不小於前一根,那麼這根木棍就不需要加時間。 題解:貪心+標記。 先按照長度由小到大排序,如果長度一樣,則按照重量由

二進位制列舉限定顏色種類數求不接觸區間總長 Wannafly26C

連結:https://www.nowcoder.com/acm/contest/212/C 來源:牛客網   七彩線段 時間限制:C/C++ 2秒,其他語言4秒 空間限制:C/C++ 262144K,其他語言524288K 64bit IO Format: %lld 題目描述

貪心演算法49. Best Time to Buy and Sell Stock

49. Best Time to Buy and Sell Stock Say you have an array for which the ith element is the price of a given stock on day&n

CF C. Maximum Subrectangle貪心 + dp

給你一個兩個陣列  分別n , m 長度 然後給你n個數  m個數   一個x 然後這n + m個數 構成一個矩形 比如 3 3   1 2 3  1 2 3 表:就是for(i=n個數) for (j=m個數) i*j 1 2 3 2 4 6 3 6

NOJ1205貪心演算法活動安排

1205.活動安排 時限:1000ms 記憶體限制:10000K  總時限:3000ms 描述 Jack是一名nwpu的大一新生,對學校舉辦的各種活動都十分的好奇,想盡可能多的參加這些活動。Npwu每天共有N項活動,其開始結束時間分別為B[i],E[i],(i = 1,

POJ1602 昂貴的聘禮Dijkstra+列舉

昂貴的聘禮 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 57139 Accepted: 17256 Description 年輕的探險家來到了一個印第安部落裡。在

Gym 101606E 貪心+sort

#include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<iostream> #define INF 0x3fffffff co