//自己弄不出的代码,感觉这种判断谓词的方式不太好控制输出。求解脱。日后再说,再次解决
#include <map> #include <set> #include <list> #include <cmath> #include<cctype> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cstdio> #include <string> #include <vector> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) { return a % b == 0 ? b : gcd(b, a % b); } long long ans[510][510]; int N,M; long long src[510]; bool flag; bool judge(long long mid) { //printf("%lld\n",mid); int segment=0,cas=0;; long long sum=0; for (int i=N-1;i>=0;i--) { sum+=src[i]; if (sum>=mid) { sum=src[i]; segment++; cas=0; ans[segment][cas++]=src[i]; } else ans[segment][cas++]=src[i]; } if (segment>=M) return false; return true; } int slove(long long low,long long high) { //if (flag) return; //printf("%lld %lld\n",low,high); if (low>high) return high+1; long long mid=(high+low)>>1; if (judge(mid)) return slove(low,mid-1); else return slove(mid+1,high); } int main() { freopen("sample.txt","r",stdin); int T; scanf("%d",&T); while (T--) { scanf("%d%d",&N,&M); long long max=0,min=10000000; memset(ans,-1,sizeof(ans)); for (int i=0;i<N;i++) { scanf("%lld",&src[i]); max+=src[i]; if (src[i]<min) min=src[i]; } flag=false; long long rr=slove(min,max); memset(ans,-1,sizeof(ans)); //printf("%lld\n",rr); judge(rr); for (int i=0;i<M;i++)//我的问题出在输出的过程中,判断谓词是否正确的时候,如果分割区间少于给予分区时,那么这种输出格式都不对, { for (int j=0;ans[i][j]!=-1;j++) printf("%lld ",ans[i][j]); if (i!=M-1)printf("/ "); } putchar('\n'); } return 0; }
下面是别人的代码d_double's
/* * UVa: 714 - Copying Books * Time: 0.008s * Author: D_Double * */ #include<cstdio> #include<cstring> #define MAXN 505 using namespace std; int m, k; long long arr[MAXN], sum, min, ans; bool vis[MAXN]; inline int divide(long long M){ memset(vis, 0, sizeof(vis)); int cnt=0; int pos=m-1; while(pos>=0){ long long sum=0; bool ok=true; while(pos>=0 && sum+arr[pos]<=M){ ok=false; sum += arr[pos]; --pos; } if(ok){ return k+1; // 返回一个大于k的数 } if(pos>=0) vis[pos] = true; ++cnt; } return cnt; } long long binary(){ long long left=min, right=sum, mid; while(left<right){ mid = (left+right)>>1; if(divide(mid)<=k) right=mid; else left=mid+1; } return right; } inline void output(){ int cnt=divide(ans); for(int i=0; i<m-1&&cnt<k; ++i)if(!vis[i]){ vis[i]=true; ++cnt; } for(int i=0; i<m; ++i){ if(i) printf(" %lld",arr[i]); else printf("%lld",arr[i]); if(vis[i]){ printf(" /"); } } puts(""); } int main(){ int T; scanf("%d",&T); while(T--){ scanf("%d%d",&m,&k); sum=0; min=0; for(int i=0; i<m; ++i){ scanf("%lld",&arr[i]); sum += arr[i]; if(arr[i]>min) min=arr[i]; } ans=binary(); output(); } return 0; }