您的位置:首页 > 其它

noi 2009 诗人小G 动态规划

2012-07-15 22:04 267 查看


思路:设前i个句子和+i为sum[i]

dp[i]表示以第i个为结尾的最小不协调度

dp[i]=min(dp[j]+abs(sum[i]-sum[j]-l)^p);

我们发现y=a1+abs(x-b1)^p和y=a2+abs(x-b2)^p至多有一个交点

所以可以用斜率优化

时间复杂度nlogMAXL

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
#define MAXN 110001
#define MAXNL 3001000
const double INF=1e18;
const long long INF2=1000000000000000000LL;
int n,l,T,p;
double dp[MAXN];
long long dp1[MAXN];
char c[MAXN][31];
int sum[MAXN],Q[MAXN],pre[MAXN],beh[MAXN];
double poww(long double x,int y)
{
return pow(fabs(x),y);
}
long long my_pow(int x,int y)
{
if(x<0) x=-x;
long long ans=1;
for(int i=1;i<=y;i++)
{
ans=ans*x;
if(ans>INF2)
return INF2+1;
}
return ans;
}
int search(int x,int y)
{
int left=-MAXNL,right=MAXNL;
while(left<right)
{
int mid=(left+right)/2;
if(dp[x]+poww(mid-sum[x],p)<dp[y]+poww(mid-sum[y],p))
left=mid;
else
right=mid;
if(right-left==1)
return left;
}
}

bool check(int x,int y,int z)
{
int num=search(y,z);
if(dp[x]+poww(num-sum[x],p)>=dp[y]+poww(num-sum[y],p))
return 0;
else return 1;
}

bool solve()
{
int i;
int left,right;
left=right=0;
Q[0]=0;
for(i=1;i<=n;i++)
{

while(left<right&&dp[Q[left]]+poww(sum[i]-l-sum[Q[left]],p)>=dp[Q[left+1]]+poww(sum[i]-l-sum[Q[left+1]],p))
left++;
dp[i]=dp[Q[left]]+poww(sum[i]-l-sum[Q[left]],p);
dp1[i]=dp1[Q[left]]+my_pow(sum[i]-l-sum[Q[left]],p);
pre[i]=Q[left]+1;
while(left<right&&check(Q[right-1],Q[right],i))
right--;
Q[++right]=i;
}
if(dp
>INF)
{
printf("Too hard to arrange\n");
return 0;
}
printf("%lld\n",dp1
);
return 1;
}
void output()
{
int i,j;
for(i=n;i>0;i=pre[i]-1)
beh[pre[i]]=i;
for(i=1;i<=n;i=beh[i]+1)
{
for(j=i;j<beh[i];j++)
printf("%s ",c[j]);
printf("%s\n",c[j]);
}
}

int main()
{
scanf("%d",&T);
while(T--)
{
sum[0]=0;
scanf("%d%d%d",&n,&l,&p);
int i,j;
for(i=1;i<=n;i++)
{
scanf("%s",c[i]);
sum[i]=sum[i-1]+strlen(c[i])+1;
};
l++;
dp1[0]=0;
dp[0]=0;
solve();
output();
printf("--------------------\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: