題目鏈結:
題目大意:有一些牛,頭要麼朝前要麼朝後,現在要求確定乙個連續反轉牛頭的區間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...