题目链接 http://acm.hust.edu.cn/vjudge/problem/19689
解题思路
寻找最小上界用二分法
打印方案时从右边(尾)尽量往左边(头)划分。段数不够的话,从最左边往右一个一个划分。
代码
#include<stdio.h> #include<string.h> //#define LOCAL typedef long long ll; int div, n; ll book[505]; bool flag[505]; void Search(ll l, ll r) { while(l<r) { bool flag1 = false; ll mid = (l+r)/2; ll sum = 0, divide = 1; for(int i=0; i<n; i++) { if(sum<mid && sum+book[i]<mid) sum+=book[i]; else if(book[i]<mid){ divide++; sum=0; sum+=book[i]; } else { flag1 = true; break; } } if(flag1 || divide > div) l = mid+1; else r = mid; } // printf("%d\n", l); ll sum = 0; for(int i=n-1; i>=0; i--) { if(sum<l && sum+book[i]<l) sum+=book[i]; else { sum = 0; flag[i] = true; sum+=book[i]; } } int di=1; int pos=0; for(int i=n-1; i>=0; i--) if(flag[i]) di++; if(di != div) for(int i=0; i<n&&di!=div; i++) if(!flag[i]) { flag[i] = true; di++; } for(int i=0; i<n; i++) if(flag[i] && i!=n-1) printf("%lld / ", book[i]); else if(i!=n-1)printf("%lld ", book[i]); else printf("%lld", book[i]); } int main() { #ifdef LOCAL freopen("data.txt", "r", stdin); freopen("ans.txt", "w", stdout); #endif int cases; ll sum = 0; scanf("%d", &cases); while(cases--) { memset(flag, 0, sizeof(flag)); scanf("%d%d", &n, &div); for(int i=0; i<n; i++) { scanf("%lld", &book[i]); sum+=book[i]; } Search(0, sum); printf("\n"); } return 0; }
时间: 2024-11-07 15:57:39