對於抄書問題1,由於標籤上寫的dp,我就寫了dp。。。。
設dp[i][j]表示前i本書由j個人抄的最小答案,則狀態轉移方程為
dp[i][j]=min,其中s為字首和,k從j-1到1列舉。
輸出方案時,由於題目要求多解時使前面的人抄的盡量少,因此可以貪心地輸出。
由於我們在前面的dp過程後已經知道了每個人抄書的頁數的最大值的最小值dp[m][k],因此可以逆序列舉第i個人,將不超過dp[m][k]的書都交給i抄,然後得出的答案保證前邊的人抄書盡可能少,這樣就能ac抄書問題1了。時間複雜度
o(k*m^2+k);
#include#define maxn 105
#define inf 0x7fffff
using namespace std;
int m,k,book[maxn],s[maxn];
struct anses;
int dp[maxn][maxn];
int main()
for(int i=2;i<=m;i++)
dp[i][j]=minx;
} }int ansxx=dp[m][k];
anses ans00[maxn];
int i=m,k0=k;
while(k0)
else if(s[i]-s[j+1]<=ansxx)
} for(int i=1;i<=k;i++)cout《但是對於抄書問題2&3,以上dp顯然不行,因此得換思路。
剛才的討論中,dp過程的作用,是求出m本書分成k份的最大代價的最小值,之後貪心地輸出就可以了,是不是有二分答案的味道?
我們可以二分查詢最大價值的最小值,然後用剛剛所得的貪心策略驗證,如果分給了》k個人,說明二分的答案偏小,反之偏大。
但是codevs的資料神坑。。。。。
由於我們剛才的貪心策略,有可能根本用不了k個人就能在最優策略下抄完m本書,此時程式將前邊的人分配了0本書!但是根據codevs上的資料,應該是每個人都至少抄一本書,呵呵。。。。
#include#define maxn 1000000+5
using namespace std;
int s[maxn],n,k,begin[maxn],end[maxn];
int main()
int lf=1,ri=s[n],ans,mid;
for(int i=1;i<=k;i++)begin[i]=end[i]=i;
while(lf>1;
int b=n,e=n,cnt=0;
while(b>=0)
if(s[e]-s[b-1]<=mid) b--;
else
} cnt++;
if(cnt>k) lf=mid+1;
else ri=mid;
} int b=n,e=n,mark=0;
for(int i=k;i>=1;i--)
b--;
} end[i]=e;
begin[i]=b+1;
e=b;
}}
codevs 3162 抄書問題
3162 抄書問題 題目描述description 現在要把m本有順序的書分給k個人複製 抄寫 每乙個人的抄寫速度都一樣,一本書不允許給兩個 或以上 的人抄寫,分給每乙個人的書,必須是連續的,比如不能把第 一 第三 第四本數給同乙個人抄寫。現在請你設計一種方案,使得複製時間最短。複製時間為抄寫頁數最...
codevs3162 抄書問題
題目描述 description 現在要把m本有順序的書分給k個人複製 抄寫 每乙個人的抄寫速度都一樣,一本書不允許給兩個 或以上 的人抄寫,分給每乙個人的書,必須是連續的,比如不能把第 一 第三 第四本數給同乙個人抄寫。現在請你設計一種方案,使得複製時間最短。複製時間為抄寫頁數最多的人用去的時間。...
codevs 3162 抄書問題
題目描述description 現在要把m本有順序的書分給k個人複製 抄寫 每乙個人的抄寫速度都一樣,一本書不允許給兩個 或以上 的人抄寫,分給每乙個人的書,必須是連續的,比如不能把第 一 第三 第四本數給同乙個人抄寫。現在請你設計一種方案,使得複製時間最短。複製時間為抄寫頁數最多的人用去的時間。輸...