木棍分割 HAOI2008

2022-02-03 12:06:59 字數 2005 閱讀 5707

有n根木棍, 第i根木棍的長度為li,n根木棍依次鏈結了一起, 總共有n-1個連線處. 現在允許你最多砍斷m個連

接處, 砍完後n根木棍被分成了很多段,要求滿足總長度最大的一段長度最小, 並且輸出有多少種砍的方法使得總長

度最大的一段長度最小. 並將結果mod 10007。。。

輸入檔案第一行有2個數n,m.接下來n行每行乙個正整數li,表示第i根木棍的長度.n<=50000,0<=m<=min(n-1,10

00),1<=li<=1000.

輸出有2個數, 第乙個數是總長度最大的一段的長度最小值, 第二個數是有多少種砍的方法使得滿足條件.

3 2                           1 1

10

10 2
兩種砍的方法: (1)(1)(10)和(1 1)(10)

題解

人生第一道二分答案成就感滿滿!二分答案,是指在最小值和最大值之間二分列舉答案,逐漸把答案縮小到乙個值得出最優解。二分答案的題目設問常常是最大值最小、最小值最大,解的可能性應該是單調的(即某值不可行則答案只能比它大或只能比它小),需要能簡單地驗證答案正確與否,要注意的就是防止死迴圈(不過這道題好像沒有這個問題)。對於木棍分割,如果這個值可行,最優解可能比它更小,以它為上界看一看有沒有更小的解;如果這個值不可行,只能捨棄它和比它更小的解,以它+1為下界搜尋答案。

int check(long long x)

}if(temp>m) return 0;

return 1;

}le=yd,jg=zd;(最小解是單段木塊長度的最大值,最大解是所有木塊長度之和)

while(le>1;

if(check(mid)) jg=mid;

else le=mid+1;

}dp部分優化空間複雜度用滾動陣列,優化時間複雜度用類似單調佇列的思路,和watching firework is fun大同小異,最後結果為f[i][n]之和。f[i][j]表示j段木塊切i次的方案,f[i][j]為所有滿足sum[i]-sum[k]<=jg的f[k][j-1]之和(1<=k

upd:關於這個二分卡死的問題後來慢慢弄清了是怎麼回事。並不是+1或不+1就容易被卡死,而是你要保證每次l和r總有乙個是變化的。比如說mid=l+r>>1,那mid可能和l相等,你就不能if(……)l=mid,如果必須這樣就得mid=(l+r+1)>>1。oi中的很多東西開始不明白,用了很長時間忽然就搞懂了,只有看清了內部的原理才是真正的通透啊。

#include#include

#include

using

namespace

std;

const

int sj=50010

;int li[sj],mod=10007

,yd;

intla,no,head,n,m,mid,temp,tail;

long

long s[sj],f[2

][sj],zd,jg,le,he,fas;

int dbj(int x,int

y)int xbj(int x,int

y)void

init()

}void

dp()

fas=f[0

][n];

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

f[no][i]=he;

f[no][i]%=mod;

}fas+=f[no][n];

fas%=mod;

}}int check(long

long

x) }

if(temp>m) return0;

return1;

}int

main()

printf(

"%lld\n

",jg);

dp();

printf(

"%lld

",fas);

//while(1);

return0;

}

HAOI2008 木棍分割

沒寫過幾道的字首和優化 dp 第一問是小學生難度的二分 第二問就直接 dp 了 設 dp i j 表示當前分割點在 i 之後,前面一共分割了 j 段的方案數 利用字首和單調性,通過二分預處理出每乙個點往前能擴充套件到的最大位置,之後字首和優化就可以啦 但是發現這個樣子空間會炸,而這個樣子還沒有辦法滾...

HAOI2008 木棍分割

description 有n根木棍,第i根木棍的長度為li,n根木棍依次鏈結了一起,總共有n 1個連線處.現在允許你最多砍斷m個連線處,砍完後n根木棍被分成了很多段,要求滿足總長度最大的一段長度最小,並且輸出有多少種砍的方法使得總長度最大的一段長度最小.並將結果mod 10007。input 輸入檔...

題解 HAOI2008木棍分割

對於這道題目的兩問,第一問直接二分答案求出最短長度。關鍵在於第二問應當如何求 建立dp方程,dp i j 代表到第i個分界線,切了j次 強制在第i處切一刀 這樣就不會對後面的狀態產生影響 狀態轉移的方程即是當前分界線列舉上一條分界線在 上一條分界線與當前線之間如果相差不超過之前二分出來的答案,就可以...