DP_1d1d诗人小G

显然:f[i]=min{f[j]+(s[i]-s[j]+i-j-1-l)^p}

此题可以基于决策单调优化

证明,反正我现在不打算学

实际上就是双向队列

不停弹出队头的元素,直到当前位置在队头元素最优的范围内。

然后,每次把当前决策插入队尾,并弹出没它优的答案。

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <cstdio>
 6 #include <vector>
 7 #include <cmath>
 8 #include <queue>
 9 #include <map>
10 #include <set>
11 using namespace std;
12 
13 typedef long double ll;
14 const int MAXN=1e5+10;
15 struct node{int l,r,p;}q[MAXN];
16 ll sum[MAXN],f[MAXN];
17 int T,n,l,p;
18 char s[35];
19 
20 ll pow(ll x){
21   int y=p;ll ret=1;
22   while(y){
23     if(y&1)ret=ret*x;
24     x*=x,y>>=1;
25   }
26   return ret;
27 }
28 
29 ll calc(int x,int y){
30   return f[x]+pow(abs(sum[y]-sum[x]+(y-x-1)-l));
31 }
32 
33 int find(node x,int i){
34   int l=x.l,r=x.r;
35   while(l<=r){
36     int mid=(l+r)>>1;
37     if(calc(i,mid)<=calc(x.p,mid))r=mid-1;
38     else l=mid+1;
39   }
40   return l;
41 }
42 
43 void DP_1d1d(){
44   int head=1,tail=0;
45   q[++tail]=(node){0,n,0};
46   for(int i=1;i<=n;i++){
47     if(head<=tail && q[head].r<i)head++;
48     f[i]=calc(q[head].p,i);
49     if(calc(i,n)<=calc(q[tail].p,n)){
50       while(head<=tail && calc(q[tail].p,q[tail].l)>=calc(i,q[tail].l) )tail--;
51       if(head>tail)q[++tail]=(node){i,n,i};
52       else{
53         int x=find(q[tail],i);
54         q[tail].r=x-1;
55         q[++tail]=(node){x,n,i};
56       }
57     }
58   }
59 }
60 
61 int main(){
62   scanf("%d",&T);
63   while(T--){
64     scanf("%d%d%d",&n,&l,&p);
65     for(int i=1;i<=n;i++)scanf("%s",s),sum[i]=sum[i-1]+strlen(s);
66     DP_1d1d();
67     if(f[n]>1e18)puts("Too hard to arrange");
68     else    printf("%lld\n",(long long)f[n]);
69     puts("--------------------");
70   }
71   return 0;
72 }
DP_1d1d

 

posted @ 2017-03-10 23:03  墨鳌  阅读(88)  评论(0编辑  收藏  举报