小a和uim來到雨林中探險。突然一陣北風吹來,一片烏雲從北部天邊急湧過來,還伴著一道道閃電,一陣陣雷聲。剎那間,狂風大作,烏雲布滿了天空,緊接著豆大的雨點從天空中打落下來,只見前方出現了乙個披頭散髮、青面獠牙的怪物,低沉著聲音說:「呵呵,既然你們來到這,只能活下來乙個!」。小a和他的小夥伴都驚呆了!
瞬間,地面上出現了乙個n*m的巨幅矩陣,矩陣的每個格仔上有一坨0~k不等量的魔液。怪物各給了小a和uim乙個魔瓶,說道,你們可以從矩陣的任乙個格仔開始,每次向右或向下走一步,從任乙個格仔結束。開始時小a用魔瓶吸收地面上的魔液,下一步由uim吸收,如此交替下去,並且要求最後一步必須由uim吸收。魔瓶只有k的容量,也就是說,如果裝了k+1那麼魔瓶會被清空成零,如果裝了k+2就只剩下1,依次類推。怪物還說道,最後誰的魔瓶裝的魔液多,誰就能活下來。小a和uim感情深厚,情同手足,怎能忍心讓小夥伴離自己而去呢?沉默片刻,小a靈機一動,如果他倆的魔瓶中魔液一樣多,不就都能活下來了嗎?小a和他的小夥伴都笑呆了!
現在他想知道他們都能活下來有多少種方法。
第一行,三個空格隔開的整數n,m,k
接下來n行,m列,表示矩陣每乙個的魔液量。同一行的數字用空格隔開。
乙個整數,表示方法數。由於可能很大,輸出對1000000007取餘後的結果。
2 2 3
1 11 1
4
題目大概就是這樣,大家讀完題以後可能馬上會想到揹包,這個題總結成一句話就是找出所有能保持兩人魔瓶中魔液相等的情況,且使uim最後操作的方案。
題目思路出來了以後,我們馬上想到的就是動態規劃陣列,但是有幾個維度,每個維度表示什麼,又需要重新考慮,前兩個維度一定時表示當前位置i,j,這是毋庸置疑的。題目要求保證二人魔液數量相等,那麼是不是代表著我們一定要開兩個維度分別來表示兩個人魔液的數量呢?
答案顯然是不用的,我們如果開兩個維度,在表示兩個人魔液數量相等的時候,還需要一次判斷操作,而且多開兩個維度占用空間也是平方級的,顯然十分不划算。正解是我們只開乙個維度,表示二者魔液差,這樣既節省了空間,又省去了一次判斷操作。然後我們還需要乙個維度,既然說題目要求最後一步需要uim操作,且第一步由小a開始,我們自然需要乙個維度來表示最後一步是小a操作還是uim操作。
然後我們就要考慮狀轉了。
先把狀轉寫出來:
嗯……沒毛病
就是這麼長
我們來解釋一下:f[i][j][p][q]表示他們走到(i,j),且兩人魔瓶內魔液量的差為p時的方法數。q=0表示最後一步是小a走的,q=1表示最後一步是uim走的。題目中說魔瓶的容量為k,實際上就是動歸時p需要對k+1取餘數,即p只有0~k,k+1種可能。答案為所有f[i][j][0][1]的和。
這樣演算法複雜度是o(n*m*k)。
這道題就這樣結束了,最後附上**:
int main()
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) for(int h=0;h<=k;h++)
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) ans=(ans+dp[i][j][0][1])%mod;
cout《這其實是一道dp或者遞推的經典題,非常適合拿來練手。
Luogu P1373 小a和uim之大逃離
題目描述 傳送門 一看這題首先想到設d i,j,k1,k 2,0 表示在小a剛吸完i,j這個位置的魔液,小a和uim的魔瓶的魔液量分別為k1,k2時的方案數,d i,j,k1,k 2,1 表示在uim剛吸完 的方案數。但是這樣明顯會爆記憶體 於是我就一直卡著了。後來看到討論區有差這個字,才想到把狀態...
luogu P1373 小a和uim之大逃離
這是一道求方案數的題。我很菜,不太會寫方案數的題,所以看了下題解,並寫下這篇部落格。首先,我們是在乙個n m的格仔裡走,有兩種走法,乙個是向右,乙個是向下。起點任意,終點任意。在你走的路徑上,第奇數個點是小a取走其中的液體,第偶數個點是uim取走其中的液體,必須走偶數個點。我們所要求的是,走到終點後...
luogu P1373 小a和uim之大逃離
小a和uim來到雨林中探險。突然一陣北風吹來,一片烏雲從北部天邊急湧過來,還伴著一道道閃電,一陣陣雷聲。剎那間,狂風大作,烏雲布滿了天空,緊接著豆大的雨點從天空中打落下來,只見前方出現了乙個披頭散髮 青面獠牙的怪物,低沉著聲音說 呵呵,既然你們來到這,只能活下來乙個!小a和他的小夥伴都驚呆了!瞬間,...