noi 2009 诗人小G 动态规划

思路:设前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

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstring>
  5 using namespace std;
  6 #define MAXN 110001
  7 #define MAXNL 3001000
  8 const double INF=1e18;
  9 const long long INF2=1000000000000000000LL;
 10 int n,l,T,p;
 11 double dp[MAXN];
 12 long long dp1[MAXN];
 13 char c[MAXN][31];
 14 int sum[MAXN],Q[MAXN],pre[MAXN],beh[MAXN];
 15 double poww(long double x,int y)
 16 {
 17     return pow(fabs(x),y);
 18 }
 19 long long my_pow(int x,int y)
 20 {
 21     if(x<0) x=-x;
 22     long long ans=1;
 23     for(int i=1;i<=y;i++)
 24     {
 25         ans=ans*x;
 26         if(ans>INF2)
 27             return INF2+1;
 28     }
 29     return ans;
 30 }
 31 int search(int x,int y)
 32 {
 33     int left=-MAXNL,right=MAXNL;
 34     while(left<right)
 35     {
 36         int mid=(left+right)/2;
 37         if(dp[x]+poww(mid-sum[x],p)<dp[y]+poww(mid-sum[y],p))
 38             left=mid;
 39         else
 40             right=mid;
 41         if(right-left==1)
 42             return left;
 43     }
 44 }
 45   
 46 bool check(int x,int y,int z)
 47 {
 48     int num=search(y,z);
 49     if(dp[x]+poww(num-sum[x],p)>=dp[y]+poww(num-sum[y],p))
 50         return 0;
 51     else return 1;
 52 }
 53   
 54 bool solve()
 55 {
 56     int i;
 57     int left,right;
 58     left=right=0;
 59     Q[0]=0; 
 60     for(i=1;i<=n;i++)
 61     {
 62  
 63         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))
 64             left++;
 65         dp[i]=dp[Q[left]]+poww(sum[i]-l-sum[Q[left]],p);
 66         dp1[i]=dp1[Q[left]]+my_pow(sum[i]-l-sum[Q[left]],p);
 67         pre[i]=Q[left]+1;
 68         while(left<right&&check(Q[right-1],Q[right],i))
 69             right--;
 70         Q[++right]=i;
 71     }
 72     if(dp[n]>INF)
 73     {
 74         printf("Too hard to arrange\n");
 75         return 0;
 76     }
 77     printf("%lld\n",dp1[n]);
 78     return 1;
 79 }
 80 void output()
 81 {
 82     int i,j;
 83     for(i=n;i>0;i=pre[i]-1)
 84         beh[pre[i]]=i;
 85     for(i=1;i<=n;i=beh[i]+1)
 86     {
 87         for(j=i;j<beh[i];j++)
 88             printf("%s ",c[j]);
 89         printf("%s\n",c[j]);
 90     }
 91 }
 92   
 93 int main()
 94 {
 95     scanf("%d",&T);
 96     while(T--)
 97     {
 98         sum[0]=0;
 99         scanf("%d%d%d",&n,&l,&p);
100         int i,j;
101         for(i=1;i<=n;i++)
102         {
103             scanf("%s",c[i]);
104             sum[i]=sum[i-1]+strlen(c[i])+1;
105         };
106         l++;
107         dp1[0]=0;
108         dp[0]=0;
109         solve();
110         output();
111         printf("--------------------\n");
112     }
113     return 0;
114 }

posted on 2012-07-15 22:04  myoi  阅读(980)  评论(0编辑  收藏  举报

导航