日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

06:月度开销

發布時間:2023/12/10 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 06:月度开销 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:http://noi.openjudge.cn/ch0111/06/

總時間限制: 1000ms 內存限制: 65536kB
描述
  農夫約翰是一個精明的會計師。他意識到自己可能沒有足夠的錢來維持農場的運轉了。他計算出并記錄下了接下來 N (1 ≤ N ≤ 100,000) 天里每天需要的開銷。

  約翰打算為連續的M (1 ≤ M ≤ N) 個財政周期創建預算案,他把一個財政周期命名為fajo月。每個fajo月包含一天或連續的多天,每天被恰好包含在一個fajo月里。

  約翰的目標是合理安排每個fajo月包含的天數,使得開銷最多的fajo月的開銷盡可能少。

輸入
  第一行包含兩個整數N,M,用單個空格隔開。
  接下來N行,每行包含一個1到10000之間的整數,按順序給出接下來N天里每天的開銷。
輸出
  一個整數,即最大月度開銷的最小值。

樣例輸入
7 5
100
400
300
100
500
101
400
樣例輸出
500
輸入輸出樣例說明
  若約翰將前兩天作為一個月,第三、四兩天作為一個月,最后三天各自作為一個月,則最大月度開銷為500。其他任何分配方案都會比這個值更大。

先看AC代碼:

1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 int check(long *a,long N,long long mid,long M); 5 int main() 6 { 7 long N,M; 8 long *a=NULL,i; 9 long long left=0,right=0,mid=0; 10 int res; 11 12 scanf("%ld%ld",&N,&M); 13 a=(long*)malloc(N*sizeof(long)); 14 memset(a,0,N); 15 for(i=0;i<N;i++) 16 { 17 scanf("%ld",&a[i]); 18 if(a[i]>left) left=a[i]; 19 right=right+a[i]; 20 } 21 22 while(left<right) 23 { 24 mid=left+(right-left)/2; 25 res=check(a,N,mid,M); 26 if(res==1) right=mid; 27 else left=mid+1; 28 } 29 printf("%lld\n",left); 30 return 0; 31 } 32 33 //假設最大月開銷為mid,統計需要分成多少個月.然后看月的個數是否太多或太少 34 int check(long *a,long N,long long mid,long M) 35 { 36 long count=1,i,temp=0; 37 for(i=0;i<N;i++) 38 { 39 if(temp+a[i]<=mid) temp=temp+a[i];//把第i天歸入到當前第count月 40 else if(a[i]<=mid)//可以獨立成一個月 41 { 42 count++;//開始一個新的月 43 temp=a[i]; 44 if(count>M) return -1;//最大月開銷太小,導致分的組太多了。 45 } 46 else return -1;//最大月開銷mid太小了,導致某些開銷比較大的天單獨構成一個月都不行。 47 } 48 if(count>M) return -1; 49 else if(count<=M) return 1;//最大月開銷mid太大了,導致分的組太少了 50 }

思路說明:

題目的意思一定要理解清楚!!!“合理安排每個fajo月包含的天數,使得開銷最多的fajo月的開銷盡可能少。” ? “輸出一個整數,即最大月度開銷的最小值。

就是把所有天劃分為若干個段,先求出每個段里面的數字之和,然后統計各段累加和的最大值,這個值要盡可能小。現在要找的就是這個“累加和的最大值” ? 最小可以是多少。

?首先,這個題目應該二分,因為解的區間是可以明確的,可以對該區間進行二分求的真正的解。

假設二分的區間left~right,其中left是n天開銷中最大的那一個數字,right是n天開銷的總和。 ?(設想一個極限情況,要使得每一個月開銷盡量小,那么每一天都單獨做一個月就好啦,于是這個時候的月開銷最大值就是n天中每天開銷最大的值,所以left可以取max(a1,......,an)。 ? ?再設想另一種極限情況,把所有天合并在一起組成一個月,那么這個時候月開銷最大值就是sum(a1,a2,......,an),所以right取值就是n天的累加和。)

需要注意的一個地方是二分循環部分的代碼:

1 while(left<right) 2 { 3 mid=left+(right-left)/2; 4 res=check(a,N,mid,M); 5 if(res==1) right=mid; 6 else left=mid+1; 7 } 8 printf("%lld\n",left);

其中left=mid+1這里必須加上1,否則可能會死循環的。

另外,輸出值是left。這個地方也要特別注意。(請自己腦補為何是left吧)

關于子函數check(),嗯代碼注釋講的很清晰,不說了。

?

轉載于:https://www.cnblogs.com/huashanqingzhu/p/5607503.html

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的06:月度开销的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。