zoukankan      html  css  js  c++  java
  • 【洛谷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
  • 相关阅读:
    linux 中more、less 和 most 的区别
    mysql数据备份之 xtrabackup
    Web登录中的信心安全问题
    Yii2.0教程应用结构篇 —— 入口脚本
    HTML基础之JS
    HTML基础之DOM操作
    HTML基础之CSS
    HTML基础之HTML标签
    Python之unittest参数化
    Python之单元测试unittest
  • 原文地址:https://www.cnblogs.com/cdcq/p/12301418.html
Copyright © 2011-2022 走看看