您的位置:首页 > 产品设计 > UI/UE

UESTC 1214 divide && PKU 3390 Print Words in Lines [DP]

2010-05-19 22:43 435 查看
UESTC 1214 divide && PKU 3390 Print Words in Lines [DP]

两个题有些类似,都是在限定一段连续的区间内元素之和不大于给的M,都是DP解决;

UESTC的1214元素存在负数,因此贪心是不对的;

UESTC1214 二分+dp

题意:给定一个N个元素的序列,不能改变顺序,将N个元素分为M(M<=N)堆,最小化 最大的每堆的和,求之;

很容易想到对答案ans二分,因为ans满足单调性(如果ans可以的话,大于ans的值都可以满足);

然后就是判定在该ans下能否分为不大于M堆得到的“最大的每堆的和”小于等于ans;

判定部分要用dp解决,注意一个最优子结构;

令dp[i]表示前i个数分成的每堆都小于等于ans的最小堆数;

则dp[i]=min(dp[i],dp[j]+1) 其中j<i&&sum[i到j]<=ans;

复杂度为O(N^2*logN)

]#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAX=1500;
const int INF=0x1fffffff;

int dp[MAX],N,a[MAX],M,sum[MAX];
bool ok(int Line)
{
int i,j,k;
for(i=1;i<=N;i++) dp[i]=INF;
for(i=1;i<=N;i++)
{
if(sum[i]<=Line) {dp[i]=1;continue;}
for(j=i-1;j>=0;j--)
{
//if(sum[i]-sum[j]>Line) break;
if(dp[j]!=INF&&sum[i]-sum[j]<=Line)
{
dp[i]=min(dp[j]+1,dp[i]);
}
}
}
return dp
<=M;
}
int main()
{
int i,j,T;scanf("%d",&T);
while(T--)
{
scanf("%d%d",&N,&M);
sum[0]=0;
for(i=1;i<=N;i++)
{
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
}
dp[0]=0;
int l=-100000,r=100000,mid=0;
while(l<r)
{
if(ok(mid)) r=mid;
else l=mid+1;
mid=(l+r)/2;
}
printf("%d/n",mid);
}
system("pause");
return 0;
}


PKU 3390

题意:对单词进行分行,每行包括空格的字符数最多有M个;另实际该行数为s,每行权值A=(M-s)*(M-s);

目标是令权值之和最小,输出值;

此题是刚那个题的简单版本。做法类似,没有二分的部分;

另dp[i]为前i个单词分割成行后的最小值。

令s=j+1到i字符数之和,显然s<=M;

则dp[i]=min(dp[i],dp[j]+(M-s)*(M-s)); j<i;

复杂度为O(N*M);

]// poj 3390 print words in line
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAX=10100;
const int INF=0x1fffffff;

int N,M,a[MAX],sum[MAX];
int dp[MAX];
void gs()
{
int i,j;
for(i=1;i<=N;i++)
{
int tt=sum[i]+i-1;
if(tt<=M) {dp[i]=(M-tt)*(M-tt);continue;}
tt=a[i];
dp[i]=dp[i-1]+(M-tt)*(M-tt);
for(j=i-1;j>=1;j--)
{
if(tt+a[j]+1>M) break;
int yy=tt+a[j]+1;
dp[i]=min(dp[i],dp[j-1]+(M-yy)*(M-yy));
tt=yy;
}
}
}
int main()
{
int i,j,T;scanf("%d",&T);
while(T--)
{
scanf("%d%d",&M,&N);
sum[0]=0;
for(i=1;i<=N;i++)
{
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
}
gs();
//for(i=1;i<=N;i++) cout<<dp[i]<<" ";cout<<endl;
printf("%d/n",dp
);
}
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: