【洛谷1415】拆分数列

原题:

 序列长度<=500

首先需要灵稽一动,发现一条性质

因为序列上的数字固定,所以可以用两个数l和r来表示一段数[l,r],也就是说划分后的每一个数只需用两个端点来表示

我的做法是把[l,r]视为一个状态,然后n^3处理找出所有可转移的状态对,建图,跑两遍bfs……

看上去挺乱搞的,居然搞过了 = =b

实际上正解和bfs记忆化差不多,属于典型的bfs转dp的类型

dp不过是用循环枚举状态来代替状态图中的边

只要发现了一段数可以用两个端点表示的性质就能写了,例如用f[i]表示以i为终点的数的左端点下标最少是多少

判断两个数的大小可以直接第三重循环,这样dp的复杂度也是n^3的

其实直接建图跑bfs是过不了的,因为边数太多了

不过大概想象了一下,规定参与连边的状态长度不能超过50,就直接跑过了 XD

代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<time.h>
  5 using namespace std;
  6 struct edg{int nxt,y;}e[21000000];  int lk[251000],ltp=0;
  7 void ist(int x,int y){
  8     e[++ltp]=(edg){lk[x],y};  lk[x]=ltp;
  9     e[++ltp]=(edg){lk[y],x};  lk[y]=ltp;
 10     //cout<<x<<" "<<y<<endl;
 11 }
 12 char s[510];  int a[510],n;
 13 int q[251000],hd=0;
 14 bool clr[251000];
 15 int ans=0;
 16 int gtid(int x,int y){  return (x-1)*n+y-1;}
 17 void bfs1(){
 18     int N=gtid(n,n);
 19     for(int i=0;i<=N;++i)  clr[i]=false;
 20     hd=0;
 21     for(int i=1;i<=n;++i){
 22         q[++hd]=gtid(1,i);
 23         clr[gtid(1,i)]=true;
 24     }
 25     for(int k=1;k<=hd;++k){
 26         //printf("(%d, %d)
",q[k]/n+1,q[k]%n+1);
 27         for(int i=lk[q[k]];i;i=e[i].nxt){
 28             if(e[i].y/n+1==q[k]%n+1+1 && !clr[e[i].y]){
 29                 clr[e[i].y]=true;
 30                 q[++hd]=e[i].y;
 31             }
 32         }
 33     }
 34 }
 35 void bfs2(){
 36     int N=gtid(n,n);
 37     for(int i=0;i<=N;++i)  clr[i]=false;
 38     //注意id可以是0
 39     q[hd=1]=gtid(ans,n);
 40     clr[gtid(ans,n)]=true;
 41     //for(int i=ans-1;i>=1;--i)if(!a[i]){
 42     for(int i=ans-1;i>=1 && !a[i];--i){
 43         q[++hd]=gtid(i,n);
 44         clr[gtid(i,n)]=true;
 45     }
 46     for(int k=1;k<=hd;++k){
 47         //printf("(%d, %d)
",q[k]/n+1,q[k]%n+1);
 48         for(int i=lk[q[k]];i;i=e[i].nxt)if(e[i].y%n+1==q[k]/n+1-1 && !clr[e[i].y]){
 49             clr[e[i].y]=true;
 50             q[++hd]=e[i].y;
 51         }
 52     }
 53 }
 54 bool chck(int x,int y,int z){
 55     int l1=x,l2=y+1;
 56     for(;!a[l1];++l1);
 57     for(;!a[l2];++l2);
 58     if(y-l1+1<z-l2+1)  return true;
 59     if(y-l1+1>z-l2+1)  return false;
 60     for(int i=0;l1+i<=y;++i){
 61         if(a[l1+i]<a[l2+i])  return true;
 62         if(a[l1+i]>a[l2+i])  return false;
 63     }
 64     return false;
 65 }
 66 int main(){
 67     //int t0=clock();
 68 
 69     scanf("%s",s+1);  n=strlen(s+1);
 70     for(int i=1;i<=n;++i)  a[i]=s[i]-'0';
 71 /*    
 72     n=500;
 73     for(int i=1;i<=n;++i)  a[i]=9;
 74     cout<<"input: "<<clock()-t0<<endl;
 75     t0=clock();
 76 */
 77     for(int i=1;i<=n;++i)for(int j=i+1;j<=n;++j)
 78         //for(int k=i;k<j;++k)if(chck(i,k,j)){
 79         for(int k=i;k<j;++k)if(k-i+1<=50 && j-k<=50 && chck(i,k,j)){
 80             ist(gtid(i,k),gtid(k+1,j));
 81             //printf("(%d, %d) -> (%d, %d)
",i,k,k+1,j);
 82         }
 83 
 84     //cout<<"insert: "<<clock()-t0<<endl;
 85     //t0=clock();
 86 
 87     bfs1();
 88     for(int i=n;i>=1;--i)if(clr[gtid(i,n)]){
 89         ans=i;
 90         break;
 91     }
 92 
 93     //cout<<"bfs1: "<<clock()-t0<<endl;
 94     //t0=clock();
 95 
 96     bfs2();
 97     int l=1,r=0;
 98     for(int i=n;i>=1;--i)if(clr[gtid(1,i)]){
 99         r=i;
100         break;
101     }
102 
103     //cout<<"bfs2: "<<clock()-t0<<endl;
104     //t0=clock();
105 
106     hd=0;  //注意如果加了r!=n的判断hd可能不会被重制
107     if(r!=n)  q[hd=1]=r;
108     for(;r<n;){
109         int mx=0;
110         for(int i=lk[gtid(l,r)];i;i=e[i].nxt)if(e[i].y/n+1==r+1 && clr[e[i].y])
111             mx=max(mx,e[i].y%n+1);
112         l=r+1,r=mx;
113         if(r==n)  break;
114         q[++hd]=r;
115     }
116 
117     //cout<<"ans: "<<clock()-t0<<endl;
118     //t0=clock();
119 
120     for(int i=1,j=1;i<=n;++i){
121         printf("%d",a[i]);
122         if(j<=hd && i==q[j]){
123             printf(",");
124             ++j;
125         }
126     }
127     printf("
");
128 /*
129     cout<<"output: "<<clock()-t0<<endl;
130     for(;;){
131     }
132 */
133     return 0;
134 }
View Code
原文地址:https://www.cnblogs.com/cdcq/p/12301418.html