题目链接:http://poj.org/problem?id=1505
题目大意及思路:m个抄写员抄写n篇文章,使工作量最大的尽量小,且输出最小字典序。有两种方法可以做,dp和二分答案,二分答案较快。
dp:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<queue>
#include<algorithm>
#include<vector>
#include<stack>
#include<list>
#include<iostream>
#include<map>
using namespace std;
#define inf 0x7fffffff
#define Max 110
int max(int a,int b)
{
return a>b?a:b;
}
int min(int a,int b)
{
return a<b?a:b;
}
int t,n,m;
int a[550];
__int64 dp[550][550];
int rec[550][550];
__int64 sum[550];
int ans[550];
int main()
{
int i,j,k;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
sum[0]=0;
for(i=n;i>=1;i--)
{
scanf("%d",&a[i]);
// sum[i]=sum[i-1]+a[i];
}
for(i=1;i<=n;i++)
sum[i]=sum[i-1]+a[i];
for(i=1;i<=m;i++)
{
for(j=i;j<=n;j++)
{
if(i==1)
{
dp[i][j]=sum[j];
continue;
}
dp[i][j]=inf;
for(k=i-1;k<j;k++)
{
if(max(dp[i-1][k],sum[j]-sum[k])<=dp[i][j])
{
dp[i][j]=max(dp[i-1][k],sum[j]-sum[k]);
rec[i][j]=k;
}
}
}
}
int maxn=dp[m][n];
int tmp=n;
int cnt=0;
for(i=m;i>=2;i--)
{
// printf("a");
for(j=tmp-1;j>=1;j--)
{
if(sum[tmp]-sum[j]<=maxn&&dp[i-1][j]<=maxn)
{
ans[cnt++]=j;
break;
}
}
tmp=j;
}
ans[cnt]=0;
j=n;
for(i=0;i<=cnt;i++)
{
for(;j>=1&&j>ans[i];j--)
{
printf("%d ",a[j]);
}
if(i!=cnt)
printf("/ ");
}
puts("");
}
return 0;
}
二分:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<queue>
#include<algorithm>
#include<vector>
#include<stack>
#include<list>
#include<iostream>
#include<map>
using namespace std;
#define inf 0x7fffffff
#define Max 110
int max(int a,int b)
{
return a>b?a:b;
}
int min(int a,int b)
{
return a<b?a:b;
}
int t,n,m;
int a[550];
__int64 dp[550][550];
int rec[550][550];
__int64 sum[550];
__int64 l,r,mid;
int ans[550];
bool run()
{
int i,j,tmp=0;
j=0;
for(i=1;i<=m;i++)
{
for(;;j++)
{
if(j>n||sum[j]-sum[tmp]>mid)
{
tmp=j-1;
// printf("i %d tmp %d\n",i,tmp);
break;
}
}
if(j>n)
return true;
}
//system("pause");
return false;
}
int bsearch()
{
l=sum[n]/m;r=sum[n];
while(l<=r)
{
mid=(l+r)>>1;
// printf("mid %d\n",mid);
bool tmp=run();
if(tmp==false)
{
l=mid+1;
}
else
r=mid-1;
}
return l;
}
int main()
{
int i,j,k;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
sum[0]=0;
for(i=n;i>=1;i--)
{
scanf("%d",&a[i]);
// sum[i]=sum[i-1]+a[i];
}
for(i=1;i<=n;i++)
sum[i]=sum[i-1]+a[i];
int maxn=bsearch();
int tmp=0;j=0;
for(i=1;i<=m;i++)
{
for(;;j++)
{
if(j>n||n-j<m-i||sum[j]-sum[tmp]>maxn)
{
tmp=j-1;
ans[i]=tmp;
// printf("i %d tmp %d\n",i,tmp);
break;
}
}
}
// system("pause");
ans[0]=0;
j=n;
for(i=m;i>=1;i--)
{
for(j=ans[i];j>ans[i-1];j--)
{
printf("%d ",a[j]);
}
if(i!=1)
printf("/ ");
}
puts("");
}
return 0;
}