標籤:代碼 include font output 抄襲 委託 ali 沒有 跳過
題目
| 小升初2:廢品回收 |
| 難度層級:C; 已耗用時間限制:1000ms; Runspace限制:51200KB; 代碼長度限制:2000000B |
| 試題描述 |
| 江北榨油廠每天會產生一批廢料,廠方會按照日期批次封裝起來等待回收。現在積攢了n天的廢料,廠裡財務記錄下了每天產生廢料合約價值。現在資源回收筒委託星空運輸公司將這n天的廢料分m次回收,要求按照日期的先後順序回收,資源回收筒每次撥給運輸公司的經費是一個定值ans,油廠老闆每次允許運走的廢料是不允許賒賬的,所以運輸公司每次運走的廢料價值一定不會超過ans,若運輸公司想運走第i天的廢料,必須運走第i天及之前所有還沒有運走的廢料。對資源回收筒來說,他的撥款不但要保證運輸公司能夠恰好m次運回所有的廢料,而且撥款越少越好。請你編寫程式求出符合資源回收筒要求的每次撥款數額。 |
| 輸入 |
第一行輸入兩個用空格隔開的正整數n和m 接下來有n個由空格隔開不超過10000正整數,依次表示每一天產生廢料的價值。 |
| 輸出 |
| 輸出包含一個整數,即資源回收筒每次撥款的數額 |
| 輸入樣本 |
7 5 100 400 300 100 500 101 400 |
| 輸出樣本 |
| 500 |
| 其他說明 |
| 資料範圍:1<=m<=n<=100000 |
分析
這題算得上前100題裡最難的了。要麼搜尋,要麼二分。如果您是新手的話,可以先跳過。但理解一下,燒腦一下,還是挺好的~
主要還是二分的思路。沒學的就先別看了。
通過讀入時累加最大值和“打擂台”比較最小值確定左右端點,在通過累加當前情況所需錢數判斷是否滿足條件,並同時根據情況改變端點。最終當左右端點相等時即所有情況判斷完成時,輸出左右端點中的任意一個即可。
搜尋的代碼在這裡就不給了,基本和二分的代碼一樣,搜到了再次調用就行了。
代碼
#include<bits/stdc++.h>using namespace std;int a[100005],m,n,sum,mid,l,r,s;int main(){scanf("%d%d",&n,&m);//本代碼使用分治演算法解決,若不能理解分治演算法的基本思想,請勿抄襲!為自己帶來不必要的損失!for(int i=0;i<n;i++){scanf("%d",&a[i]);r+=a[i];//計算最右端點。if(a[i]>l) l=a[i];//計算最左端點。}while(l<r)//二分條件成立。{mid=(l+r)/2;//計算當前中點。sum=1;s=0;for(int i=0;i<n;i++)//統計總錢數。{s+=a[i];if(s>mid){sum++;s=a[i];}if(sum>m) break;//如果賒賬了,說明該方案不行,結束統計,更改端點。}if(sum>m) l=mid+1;//右移左端點。else r=mid;//左移右端點。}printf("%d",l);//輸出l和r中的一個端點就行。return 0;}
搜尋的代碼:
#include<bits/stdc++.h>//搜尋涉及到對函數的調用,看不懂更別抄!!!using namespace std;int a[100005],n,m,maxn=-1,sum,mid,cnt;//maxn給一個很小的值方便讀入和特判。void WYH_dfs(int l,int r){if(l>=r)//和二分沒有本質區別{printf("%d",l);return;}mid=(l+r)/2;cnt=1;sum=0;for(int i=0;i<n;i++){sum+=a[i];if(sum>mid){sum=a[i];cnt++;}if(cnt>m) break;}if(cnt>m) WYH_dfs(mid+1,r);else WYH_dfs(l,mid);}int main(){scanf("%d%d",&n,&m);for(int i=0;i<n;i++){scanf("%d",&a[i]);sum+=a[i];if(a[i]>maxn) maxn=a[i];}WYH_dfs(maxn,sum);return 0;}
0077-小升初2:廢品回收