POJ 3276 開關問題

2021-09-08 10:30:28 字數 1257 閱讀 8358

題目鏈結

題目大意:有一些牛,頭要麼朝前要麼朝後,現在要求確定乙個連續反轉牛頭的區間k,使得所有牛都朝前,且反轉次數m盡可能小。

解題思路

首先不要看錯題意了,不是求最小k,不要二分。而且反轉區間長度一定是k,小於k是不能反轉的。

很明顯得列舉k(1...n),並且有以下反轉思路:

①從第一頭牛開始,如果朝前,不管了。看下一頭牛,如果朝後反轉k長度區間.....一直掃到區間結束。

②第一趟結束後,如果不符合要求,繼續重複①,直到所有牛都朝前。

這樣複雜度是o(n^3),5000*5000*5000,標準tle。

其實確定反轉次數只需要掃一趟就行了,沒有必要來回多趟。o(n^2)就能解決,這裡借鑑了tmeteorj

的依賴關係法,非常簡潔。

它的思路是這樣的:

f[i]儲存的當前牛與前一頭牛的關係,不同1,同0。其中設定乙個0牛,方向為f。

這樣,如果f[i]=1,則表示[i-1,i+k-1]這個區間需要反轉,其中f值變化的只有f[i]和f[i+k]。中間的值沒有變化。

對於每個k,從1掃到n-k+1,如果f[i]=1則進行反轉操作,反轉之後變化的部分立刻反饋,這樣當處理i+1時,就能保證當前狀態是處理i+1的最後一趟的狀態。

原因很簡單,在o(n^3)的方法裡,我們來回掃,不過是把值來回重複迴圈,毫無意義。使用這種關係依賴法之後,就可以避免這些毫無意義的迴圈。

對於n+k+2~n的部分,只要出現需要反轉的,則本次k是無效的。繼續看下乙個k。

否則,更新一下ansm和ansk。

#include "

cstdio

"#include

"cstring

"int f[5005],now[5005

],n,ansm,ansk;

intmain()

for(int k=1;k<=n;k++)

for(int i=n-k+2;i<=n;i++)

if(now[i])

if(cntk;}

}printf(

"%d %d\n

",ansk,ansm);

}

13594393

neopenx

3276

accepted

196k

329ms

c++648b

2014-11-03 17:24:07

poj3276(開關問題)

可算明白了.bbfbfbb 我們到達第三個f,我們需反轉。標記一下在3出反轉了 vis 3 1 對以後的影響是 1.用sum記載影響程度即sum 1 我們到達第四個,雖然是b,但是收到前面影響 sum 1 也就是變成f了。我們需要反轉。標記vis 4 1.sum再 1.即sum 2 也就是第五個會受...

poj3276 反轉 開關問題

題目大意 給你乙個長度為n的字串,包含字母f和b 你可以把區間k 乙個常數 內的所有f變成b,b變成f。為了把這個字串都變成f,求變化的最小次數和其對應的k的值 分析 挑戰程式設計競賽 反轉法的例題,此做法非書上做法 列舉k,對於每個k,只要序列最左端的b變成f,然後依次變化,得到答案 列舉起點然後...

POJ 3276 (一維開關問題)

現在有 n 個牛站一排,給你每個牛的方向。你現在每次只能反轉連續 k 個牛的方向,問把所有牛反轉到面向前方 所需要的最少操作次數 m,以及 k的值。每次反轉乙個區間後,如果左端的牛方向真確,我們便不去考慮這個牛了。故從左到右掃一邊即可,列舉k的值,整個複雜度 o n2 include include...