zoukankan      html  css  js  c++  java
  • 【算法总结】动态规划相关

    【插头dp】

    〖相关资料

    基于连通性状态压缩的动态规划问题        《插头DP——从不会到崩溃》

    〖相关题目

    1.【Ural1519】Formula 1

    题意:给一个n×m的棋盘,其中'.'是空白,'*'是障碍,求经过所有点的哈密顿回路的数目。

    分析:见资料

      1 #include<cstdio>
      2 #include<cstring>
      3 #define LL long long
      4 using namespace std;
      5 const int N=15;
      6 const int M=3e5+5;
      7 const int hash=3e5;
      8 int n,m,ex,ey,cur,pre,tot;
      9 int total[2],bit[N],first[M],state[2][M];
     10 LL anss,ans[2][M];
     11 bool map[N][N];
     12 char ch;
     13 struct edge{int to,next;}e[M];
     14 void ins(int now,LL num)
     15 {
     16     int p=now%hash;
     17     for(int i=first[p];i;i=e[i].next)
     18         if(state[cur][e[i].to]==now)
     19             {ans[cur][e[i].to]+=num;return;}
     20     total[cur]++;
     21     e[++tot]=(edge){total[cur],first[p]};
     22     first[p]=tot;
     23     state[cur][total[cur]]=now;
     24     ans[cur][total[cur]]=num;
     25 }
     26 int main()
     27 {
     28     for(int i=1;i<=13;i++)bit[i]=i*2;
     29     scanf("%d%d",&n,&m);
     30     for(int i=1;i<=n;i++)
     31         for(int j=1;j<=m;j++)
     32         {
     33             ch=getchar();
     34             while(ch!='*'&&ch!='.')ch=getchar();
     35             if(ch=='.')map[i][j]=true,ex=i,ey=j;
     36         }
     37     cur=0;total[cur]=1;
     38     ans[cur][1]=1;state[cur][1]=0;
     39     for(int i=1;i<=n;i++)
     40     {
     41         for(int j=1;j<=total[cur];j++)state[cur][j]*=4;
     42         for(int j=1;j<=m;j++)
     43         {
     44             tot=0;memset(first,0,sizeof(first));
     45             pre=cur;cur^=1;total[cur]=0;
     46             for(int k=1;k<=total[pre];k++)
     47             {
     48                 int now=state[pre][k];
     49                 LL num=ans[pre][k];
     50                 int down=(now>>bit[j-1])%4;
     51                 int right=(now>>bit[j])%4;
     52                 if(!map[i][j]){if(!down&&!right)ins(now,num);}
     53                 else if(!down&&!right)
     54                 {
     55                     int nex=now+(1<<bit[j-1])+2*(1<<bit[j]);
     56                     if(map[i+1][j]&&map[i][j+1])ins(nex,num);
     57                 }
     58                 else if(!down&&right)
     59                 {
     60                     if(map[i][j+1])ins(now,num);
     61                     int nex=now-right*(1<<bit[j])+right*(1<<bit[j-1]);
     62                     if(map[i+1][j])ins(nex,num);
     63                 }
     64                 else if(down&&!right)
     65                 {
     66                     if(map[i+1][j])ins(now,num);
     67                     int nex=now-down*(1<<bit[j-1])+down*(1<<bit[j]);
     68                     if(map[i][j+1])ins(nex,num);
     69                 }
     70                 else if(down==1&&right==1)
     71                 {
     72                     int count=1;
     73                     for(int l=j+1;l<=m;l++)
     74                     {
     75                         if((now>>bit[l])%4==1)count++;
     76                         if((now>>bit[l])%4==2)count--;
     77                         if(!count)
     78                         {
     79                             int nex=now-(1<<bit[j-1])-(1<<bit[j])-(1<<bit[l]);
     80                             ins(nex,num);break;
     81                         }
     82                     }
     83                 }
     84                 else if(down==2&&right==2)
     85                 {
     86                     int count=1;
     87                     for(int l=j-2;l>=0;l--)
     88                     {
     89                         if((now>>bit[l])%4==1)count--;
     90                         if((now>>bit[l])%4==2)count++;
     91                         if(!count)
     92                         {
     93                             int nex=now-2*(1<<bit[j-1])-2*(1<<bit[j])+(1<<bit[l]);
     94                             ins(nex,num);break;
     95                         }
     96                     }
     97                 }
     98                 else if(down==2&&right==1)
     99                 {
    100                     int nex=now-2*(1<<bit[j-1])-(1<<bit[j]);
    101                     ins(nex,num);
    102                 }
    103                 else if(down==1&&right==2&&i==ex&&j==ey)anss+=num;
    104             }
    105         }
    106     }
    107     printf("%lld
    ",anss);
    108     return 0;
    109 }
    View Code

    2.【poj1739】Tony's Tour

    题意:给一个n×m的棋盘,从左下角走到右下角,每个非障碍格子都走一遍的方法数。

    分析:见资料

      1 #include<cstdio>
      2 #include<cstring>
      3 #define LL long long
      4 using namespace std;
      5 const int N=15;
      6 const int M=1e5+5;
      7 const int hash=1e5;
      8 int n,m,ex,ey,cur,pre,tot;
      9 int total[2],bit[N],first[M],state[2][M];
     10 LL anss,ans[2][M];
     11 bool map[N][N];
     12 char ch;
     13 struct edge{int to,next;}e[M];
     14 void init()
     15 {
     16     anss=0;memset(map,0,sizeof(map));
     17     for(int i=1;i<=n;i++)
     18         for(int j=1;j<=m;j++)
     19         {
     20             ch=getchar();
     21             while(ch!='#'&&ch!='.')ch=getchar();
     22             if(ch=='.')map[i][j]=true;
     23         }
     24     n++;map[n][1]=map[n][m]=true;
     25     n++;for(int i=1;i<=m;i++)map[n][i]=true;
     26     ex=n;ey=m;cur=0;total[cur]=1;
     27     ans[cur][1]=1;state[cur][1]=0;
     28 }
     29 void ins(int now,LL num)
     30 {
     31     int p=now%hash;
     32     for(int i=first[p];i;i=e[i].next)
     33         if(state[cur][e[i].to]==now)
     34             {ans[cur][e[i].to]+=num;return;}
     35     total[cur]++;
     36     e[++tot]=(edge){total[cur],first[p]};
     37     first[p]=tot;
     38     state[cur][total[cur]]=now;
     39     ans[cur][total[cur]]=num;
     40 }
     41 void work()
     42 {
     43     for(int i=1;i<=n;i++)
     44     {
     45         for(int j=1;j<=total[cur];j++)state[cur][j]*=4;
     46         for(int j=1;j<=m;j++)
     47         {
     48             tot=0;memset(first,0,sizeof(first));
     49             pre=cur;cur^=1;total[cur]=0;
     50             for(int k=1;k<=total[pre];k++)
     51             {
     52                 int now=state[pre][k];
     53                 LL num=ans[pre][k];
     54                 int down=(now>>bit[j-1])%4;
     55                 int right=(now>>bit[j])%4;
     56                 if(!map[i][j]){if(!down&&!right)ins(now,num);}
     57                 else if(!down&&!right)
     58                 {
     59                     int nex=now+(1<<bit[j-1])+2*(1<<bit[j]);
     60                     if(map[i+1][j]&&map[i][j+1])ins(nex,num);
     61                 }
     62                 else if(!down&&right)
     63                 {
     64                     if(map[i][j+1])ins(now,num);
     65                     int nex=now-right*(1<<bit[j])+right*(1<<bit[j-1]);
     66                     if(map[i+1][j])ins(nex,num);
     67                 }
     68                 else if(down&&!right)
     69                 {
     70                     if(map[i+1][j])ins(now,num);
     71                     int nex=now-down*(1<<bit[j-1])+down*(1<<bit[j]);
     72                     if(map[i][j+1])ins(nex,num);
     73                 }
     74                 else if(down==1&&right==1)
     75                 {
     76                     int count=1;
     77                     for(int l=j+1;l<=m;l++)
     78                     {
     79                         if((now>>bit[l])%4==1)count++;
     80                         if((now>>bit[l])%4==2)count--;
     81                         if(!count)
     82                         {
     83                             int nex=now-(1<<bit[j-1])-(1<<bit[j])-(1<<bit[l]);
     84                             ins(nex,num);break;
     85                         }
     86                     }
     87                 }
     88                 else if(down==2&&right==2)
     89                 {
     90                     int count=1;
     91                     for(int l=j-2;l>=0;l--)
     92                     {
     93                         if((now>>bit[l])%4==1)count--;
     94                         if((now>>bit[l])%4==2)count++;
     95                         if(!count)
     96                         {
     97                             int nex=now-2*(1<<bit[j-1])-2*(1<<bit[j])+(1<<bit[l]);
     98                             ins(nex,num);break;
     99                         }
    100                     }
    101                 }
    102                 else if(down==2&&right==1)
    103                 {
    104                     int nex=now-2*(1<<bit[j-1])-(1<<bit[j]);
    105                     ins(nex,num);
    106                 }
    107                 else if(down==1&&right==2&&i==ex&&j==ey)anss+=num;
    108             }
    109         }
    110     }
    111     printf("%lld
    ",anss);
    112 }
    113 int main()
    114 {
    115     for(int i=1;i<=10;i++)bit[i]=i*2;
    116     scanf("%d%d",&n,&m);
    117     while(n||m)
    118     {
    119         init();work();
    120         scanf("%d%d",&n,&m);
    121     }
    122     return 0;
    123 }
    View Code

    3.【hdu1693】Eat theTrees

    题意:一个棋盘上有0,1。需要找一些回路把1全部串起来,问总方法数。

    分析:见资料

     1 #include<cstdio>
     2 #include<cstring>
     3 #define LL long long
     4 using namespace std;
     5 const int N=15;
     6 int T,n,m,p,mx,map[N][N];
     7 LL f[N][N][1<<12];
     8 int read()
     9 {
    10     int x=0,f=1;char c=getchar();
    11     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    12     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    13     return x*f;
    14 }
    15 int main()
    16 {
    17     T=p=read();
    18     while(T--)
    19     {
    20         memset(f,0,sizeof(f));
    21         n=read();m=read();
    22         mx=1<<(m+1);
    23         for(int i=0;i<n;i++)
    24             for(int j=0;j<m;j++)
    25                 map[i][j]=read();
    26         f[0][0][0]=1;
    27         for(int i=0;i<n;i++)
    28         {
    29             for(int j=0;j<m;j++)
    30                 for(int k=0;k<mx;k++)
    31                 {
    32                     if(!f[i][j][k])continue;
    33                     int down=k&(1<<j),right=k&(1<<m);
    34                     LL num=f[i][j][k];
    35                     if(!map[i][j])
    36                     {
    37                         if(!down&&!right)f[i][j+1][k]+=num;
    38                         continue;
    39                     }
    40                     if(down&&right)f[i][j+1][k-(1<<j)-(1<<m)]+=num;
    41                     if(!down&&!right)f[i][j+1][k+(1<<j)+(1<<m)]+=num;
    42                     if(down&&!right)
    43                     {
    44                         f[i][j+1][k]+=num;
    45                         f[i][j+1][k-(1<<j)+(1<<m)]+=num;
    46                     }
    47                     if(!down&&right)
    48                     {
    49                         f[i][j+1][k]+=num;
    50                         f[i][j+1][k+(1<<j)-(1<<m)]+=num;
    51                     }
    52                 }
    53             for(int k=0;k<mx/2;k++)f[i+1][0][k]=f[i][m][k];
    54         }
    55         printf("Case %d: There are %lld ways to eat the trees.
    ",p-T,f[n][0][0]);
    56     }
    57     return 0;
    58 }
    View Code

    4.【bzoj1187】[HNOI2007]神奇游乐园

    题意:给定一个四联通的网格图,每个点有个权值,求一个长度至少为4的简单环使得环上权值和最大 。

    分析:见资料

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define LL long long 
      5 using namespace std;
      6 const int N=10;
      7 const int M=1e4+5;
      8 const int hash=1e4;
      9 int n,m,cur,pre,tot,anss,map[N*12][N];
     10 int total[2],bit[N],first[M],state[2][M],ans[2][M];
     11 struct edge{int to,next;}e[M];
     12 int read()
     13 {
     14     int x=0,f=1;char c=getchar();
     15     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
     16     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
     17     return x*f;
     18 }
     19 void ins(int now,int num)
     20 {
     21     int p=now%hash;
     22     for(int i=first[p];i;i=e[i].next)
     23         if(state[cur][e[i].to]==now)
     24             {ans[cur][e[i].to]=max(ans[cur][e[i].to],num);return;}
     25     total[cur]++;
     26     e[++tot]=(edge){total[cur],first[p]};
     27     first[p]=tot;
     28     state[cur][total[cur]]=now;
     29     ans[cur][total[cur]]=num;
     30 }
     31 int main()
     32 {
     33     n=read();m=read();
     34     for(int i=1;i<=m;i++)bit[i]=i*2;
     35     for(int i=1;i<=n;i++)
     36         for(int j=1;j<=m;j++)
     37             map[i][j]=read();
     38     cur=0;total[cur]=1;
     39     ans[cur][1]=0;state[cur][1]=0;
     40     anss=-0x3f3f3f3f;
     41     for(int i=1;i<=n;i++)
     42     {
     43         for(int j=1;j<=total[cur];j++)state[cur][j]*=4;
     44         for(int j=1;j<=m;j++)
     45         {
     46             tot=0;memset(first,0,sizeof(first));
     47             pre=cur;cur^=1;total[cur]=0;
     48             for(int k=1;k<=total[pre];k++)
     49             {
     50                 int now=state[pre][k],num=ans[pre][k]+map[i][j];
     51                 int down=(now>>bit[j-1])%4,right=(now>>bit[j])%4;
     52                 if(!down&&!right)
     53                 {
     54                     ins(now,num-map[i][j]);
     55                     int nex=now+(1<<bit[j-1])+2*(1<<bit[j]);
     56                     if(i!=n&&j!=m)ins(nex,num);
     57                 }
     58                 else if(!down&&right)
     59                 {
     60                     if(j!=m)ins(now,num);
     61                     int nex=now-right*(1<<bit[j])+right*(1<<bit[j-1]);
     62                     if(i!=n)ins(nex,num);
     63                 }
     64                 else if(down&&!right)
     65                 {
     66                     if(i!=n)ins(now,num);
     67                     int nex=now-down*(1<<bit[j-1])+down*(1<<bit[j]);
     68                     if(j!=m)ins(nex,num);
     69                 }
     70                 else if(down==1&&right==1)
     71                 {
     72                     int count=1;
     73                     for(int l=j+1;l<=m;l++)
     74                     {
     75                         if((now>>bit[l])%4==1)count++;
     76                         if((now>>bit[l])%4==2)count--;
     77                         if(!count)
     78                         {
     79                             int nex=now-(1<<bit[j-1])-(1<<bit[j])-(1<<bit[l]);
     80                             ins(nex,num);break;
     81                         }
     82                     }
     83                 }
     84                 else if(down==2&&right==2)
     85                 {
     86                     int count=1;
     87                     for(int l=j-2;l>=0;l--)
     88                     {
     89                         if((now>>bit[l])%4==1)count--;
     90                         if((now>>bit[l])%4==2)count++;
     91                         if(!count)
     92                         {
     93                             int nex=now-2*(1<<bit[j-1])-2*(1<<bit[j])+(1<<bit[l]);
     94                             ins(nex,num);break;
     95                         }
     96                     }
     97                 }
     98                 else if(down==2&&right==1)
     99                 {
    100                     int nex=now-2*(1<<bit[j-1])-(1<<bit[j]);
    101                     ins(nex,num);
    102                 }
    103                 else if(down==1&&right==2&&now==(1<<bit[j-1])+2*(1<<bit[j]))
    104                     anss=max(anss,num);
    105             }
    106         }
    107     }
    108     printf("%d",anss);
    109     return 0;
    110 }
    View Code

    5.【bzoj2331】[SCOI2011]地板

    题意:见原题

    分析:公子の博客

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<iostream>
      5 using namespace std;
      6 const int mod=20110520;
      7 const int N=15;
      8 const int M=2e5+5;
      9 const int hash=1e5;
     10 int n,m,pre,cur,tot,anss,total[2];
     11 int bit[N],first[M],state[2][M],ans[2][M];
     12 char s[105];
     13 bool map[105][N];
     14 struct edge{int to,next;}e[M];
     15 void ins(int now,int num)
     16 {
     17     int p=now%hash;
     18     for(int i=first[p];i;i=e[i].next)
     19         if(state[cur][e[i].to]==now)
     20             {ans[cur][e[i].to]=(ans[cur][e[i].to]+num)%mod;return;}
     21     total[cur]++;
     22     e[++tot]=(edge){total[cur],first[p]};
     23     first[p]=tot;
     24     state[cur][total[cur]]=now;
     25     ans[cur][total[cur]]=num;
     26 }
     27 void init()
     28 {
     29     for(int i=1;i<=10;i++)bit[i]=i*2;
     30     scanf("%d%d",&n,&m);
     31     if(n<m)
     32     {
     33         for(int i=1;i<=n;i++)
     34         {
     35             scanf("%s",s+1);
     36             for(int j=1;j<=m;j++)
     37                 if(s[j]=='_')map[j][i]=true;
     38         }
     39         swap(n,m);return;
     40     }
     41     for(int i=1;i<=n;i++)
     42     {
     43         scanf("%s",s+1);
     44         for(int j=1;j<=m;j++)
     45             if(s[j]=='_')map[i][j]=true;
     46     }
     47 }
     48 void work()
     49 {
     50     cur=0;total[cur]=1;
     51     ans[cur][1]=1;state[cur][1]=0;
     52     for(int i=1;i<=n;i++)
     53     {
     54         for(int j=1;j<=total[cur];j++)state[cur][j]*=4;
     55         for(int j=1;j<=m;j++)
     56         {
     57             tot=0;memset(first,0,sizeof(first));
     58             pre=cur;cur^=1;total[cur]=0;
     59             for(int k=1;k<=total[pre];k++)
     60             {
     61                 int now=state[pre][k],num=ans[pre][k],nex;
     62                 int down=(now>>bit[j-1])%4;
     63                 int right=(now>>bit[j])%4;
     64                 if(down==1&&right==2)continue;
     65                 if(down==2&&right==1)continue;
     66                 if(down==2&&right==2)continue;
     67                 if(!map[i][j]){if(!down&&!right)ins(now,num);continue;}
     68                 if(!down&&!right)
     69                 {
     70                     nex=now+(1<<bit[j-1]);
     71                     if(map[i+1][j])ins(nex,num);
     72                     nex=now+(1<<bit[j]);
     73                     if(map[i][j+1])ins(nex,num);
     74                     nex=now+2*(1<<bit[j-1])+2*(1<<bit[j]);
     75                     if(map[i+1][j]&&map[i][j+1])ins(nex,num);
     76                 }
     77                 else if(!down&&right==1)
     78                 {
     79                     nex=now+(1<<bit[j-1])-(1<<bit[j]);
     80                     if(map[i+1][j])ins(nex,num);
     81                     nex=now+(1<<bit[j]);
     82                     if(map[i][j+1])ins(nex,num);
     83                 }
     84                 else if(down==1&&!right)
     85                 {
     86                     nex=now+(1<<bit[j])-(1<<bit[j-1]);
     87                     if(map[i][j+1])ins(nex,num);
     88                     nex=now+(1<<bit[j-1]);
     89                     if(map[i+1][j])ins(nex,num);
     90                 }
     91                 else if(!down&&right==2)
     92                 {
     93                     ins(now-2*(1<<bit[j]),num);
     94                     nex=now+2*(1<<bit[j-1])-2*(1<<bit[j]);
     95                     if(map[i+1][j])ins(nex,num);
     96                 }
     97                 else if(down==2&&!right)
     98                 {
     99                     ins(now-2*(1<<bit[j-1]),num);
    100                     nex=now+2*(1<<bit[j])-2*(1<<bit[j-1]);
    101                     if(map[i][j+1])ins(nex,num);
    102                 }
    103                 else if(down==1&&right==1)
    104                 {
    105                     nex=now-(1<<bit[j-1])-(1<<bit[j]);
    106                     ins(nex,num);
    107                 }
    108             }
    109 //            printf("QAQ %d
    ",total[cur]);
    110 //            for(int j=1;j<=total[cur];j++)
    111 //                printf("[%d] %d
    ",state[cur][j],ans[cur][j]);
    112         }
    113     }
    114     for(int i=first[0];i;i=e[i].next)
    115         if(state[cur][e[i].to]==0)
    116             {anss=ans[cur][e[i].to];break;}
    117     printf("%d",anss);
    118 }
    119 int main()
    120 {
    121     init();work(); 
    122     return 0;
    123 }
    View Code

    【斜率优化dp】

    〖相关资料

    《斜率优化DP》

    〖相关题目

    1.【bzoj1010】[HNOI2008]玩具装箱toy

    题意:见原题

    分析:无

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 using namespace std;
     5 const int N=50050;
     6 int n,L,C,c[N],q[N];
     7 long long f[N],s[N];
     8 long long read()
     9 {
    10     long long x=0,k=1;char c=getchar();
    11     while(c<'0'||c>'9'){if(c=='-')k=-1;c=getchar();}
    12     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    13     return x*k;
    14 }
    15 long long sum(long long x){return x*x;}
    16 double slope(int j,int k){return (f[k]-f[j]+sum(s[k]+C)-sum(s[j]+C))/(2.0*(s[k]-s[j]));}
    17 void dp()
    18 {
    19     int l=1,r=0;q[++r]=0;
    20     for(int i=1;i<=n;i++)
    21     {
    22         while(l<r&&slope(q[l],q[l+1])<=s[i])l++;
    23         int t=q[l];
    24         f[i]=f[t]+sum(s[i]-s[t]-C);
    25         while(l<r&&slope(q[r-1],q[r])>slope(q[r],i))r--;
    26         q[++r]=i;
    27     }
    28 }
    29 int main()
    30 {
    31     n=read();L=read();C=L+1;
    32     for(int i=1;i<=n;i++)
    33         c[i]=read(),s[i]=s[i-1]+c[i]+1;
    34     dp();
    35     printf("%lld",f[n]);
    36     return 0;
    37 }
    View Code

    2.【bzoj1911】[Apio2010]特别行动队

    题意:见原题

    分析:无

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 using namespace std;
     5 const int N=1000050;
     6 int n,a,b,c,x[N],q[N];
     7 long long s[N],f[N];
     8 long long read()
     9 {
    10     long long x=0,k=1;char c=getchar();
    11     while(c<'0'||c>'9'){if(c=='-')k=-1;c=getchar();}
    12     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    13     return x*k;
    14 }
    15 long long sum(long long x){return x*x;}
    16 double slope(int k,int j){return (f[j]-f[k]+a*(sum(s[j])-sum(s[k]))+b*(s[k]-s[j]))/(2.0*a*(s[j]-s[k]));}
    17 int main()
    18 {
    19     int l=0,r=0;
    20     n=read();a=read();b=read();c=read();
    21     for(int i=1;i<=n;i++)x[i]=read(),s[i]=s[i-1]+x[i];
    22     for(int i=1;i<=n;i++)
    23     {
    24         while(l<r&&slope(q[l],q[l+1])<s[i])l++;
    25         int t=q[l];
    26         f[i]=f[t]+a*sum(s[i]-s[t])+b*(s[i]-s[t])+c;
    27         while(l<r&&slope(q[r],i)<slope(q[r-1],q[r]))r--;
    28         q[++r]=i;
    29     }
    30     printf("%lld",f[n]);
    31     return 0;
    32 }
    View Code

    3.【bzoj1096】[ZJOI2007]仓库建设

    题意:见原题

    分析:无

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=1000050;
     6 int n,l,r,q[N];
     7 long long f[N],x[N],p[N],c[N],num[N],sum[N];
     8 long long read()
     9 {
    10     long long x=0,k=1;char c=getchar();
    11     while(c<'0'||c>'9'){if(c=='-')k=-1;c=getchar();}
    12     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    13     return x*k;
    14 }
    15 double slope(int k,int j){return (f[j]-f[k]+sum[j]-sum[k])/(1.0*(num[j]-num[k]));}
    16 int main()
    17 {
    18     n=read();
    19     for(int i=1;i<=n;i++)
    20     {
    21         x[i]=read();p[i]=read();c[i]=read();
    22         num[i]=num[i-1]+p[i];
    23         sum[i]=sum[i-1]+p[i]*x[i];
    24     }
    25     for(int i=1;i<=n;i++)
    26     {
    27         while(l<r&&slope(q[l],q[l+1])<x[i])l++;
    28         int t=q[l];
    29         f[i]=f[t]+(num[i]-num[t])*x[i]-(sum[i]-sum[t])+c[i];
    30         while(l<r&&slope(q[r],i)<slope(q[r-1],q[r]))r--;
    31         q[++r]=i;
    32     }
    33     printf("%lld",f[n]);
    34     return 0;
    35 }
    View Code

    4.【bzoj3675】[Apio2014]序列分割

    题意:见原题

    分析:无

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=100050;
     6 int n,k,l,r,num,a[N],q[N];
     7 long long s[N],f[N],g[N];
     8 long long read()
     9 {
    10     long long x=0,k=1;char c=getchar();
    11     while(c<'0'||c>'9'){if(c=='-')k=-1;c=getchar();}
    12     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    13     return x*k;
    14 }
    15 double slope(int k,int j){return (s[k]*s[k]-s[j]*s[j]+g[j]-g[k])/(1.0*s[k]-s[j]);}
    16 int main()
    17 {
    18     n=read();k=read();
    19     for(int i=1;i<=n;i++)
    20     {
    21         a[i]=read();
    22         if(a[i])
    23         {
    24             a[++num]=a[i];
    25             s[num]=s[num-1]+a[num];
    26         }
    27     }
    28     n=num;
    29     for(int i=1;i<=k;i++)
    30     {
    31         l=1;r=0;
    32         for(int j=i;j<=n;j++)
    33         {
    34             while(l<r&&slope(q[r],j-1)<slope(q[r-1],q[r]))r--;
    35             q[++r]=j-1;
    36             while(l<r&&slope(q[l],q[l+1])<s[j])l++;
    37             int t=q[l];
    38             f[j]=g[t]+(s[j]-s[t])*s[t];
    39         }
    40         for(int j=i;j<=n;j++)swap(f[j],g[j]);
    41     }
    42     printf("%lld",g[n]);
    43     return 0;
    44 }
    View Code

    5.【bzoj1597】[Usaco2008 Mar]土地购买

    题意:见原题

    分析:见资料

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 using namespace std;
     5 const int N=50050;
     6 int n,cnt,q[N];
     7 long long x[N],y[N],f[N];
     8 struct node{long long x,y;}a[N];
     9 bool cmp(node a,node b){return a.x==b.x?a.y<b.y:a.x<b.x;}
    10 long long read()
    11 {
    12     long long x=0,f=1;char c=getchar();
    13     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    14     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    15     return x*f;
    16 }
    17 double slope(int k,int j){return (double)(f[j]-f[k])/(y[k+1]-y[j+1]);}
    18 int main()
    19 {
    20     n=read();
    21     for(int i=1;i<=n;i++)
    22         a[i].x=read(),a[i].y=read();
    23     sort(a+1,a+n+1,cmp);
    24     for(int i=1;i<=n;i++)
    25     {
    26         while(cnt&&a[i].y>=y[cnt])cnt--;
    27         x[++cnt]=a[i].x;y[cnt]=a[i].y;
    28     }
    29     int l=0,r=0;
    30     for(int i=1;i<=n;i++)
    31     {
    32         while(l<r&&slope(q[l],q[l+1])<x[i])l++;
    33         int t=q[l];
    34         f[i]=f[t]+y[t+1]*x[i];
    35         while(l<r&&slope(q[r-1],q[r])>slope(q[r],i))r--;
    36         q[++r]=i;
    37     }
    38     printf("%lld",f[cnt]);
    39     return 0;
    40 }
    View Code

    6.【bzoj3156】防御准备

    题意:见原题

    分析:见资料

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 using namespace std;
     5 const int N=1000050;
     6 long long a[N],f[N],n,t,q[N],l=0,r=0;
     7 long long read()
     8 {
     9     long long x=0,f=1;char c=getchar();
    10     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    11     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    12     return x*f;
    13 }
    14 double slope(long long k,long long j)
    15 {return (2.0*(f[j]-f[k])+j*(j+1)-k*(k+1))/(2.0*(j-k));}
    16 int main()
    17 {
    18     n=read();
    19     for(int i=1;i<=n;i++)a[i]=read();
    20     for(long long i=1;i<=n;i++)
    21     {
    22         while(l<r&&slope(q[l],q[l+1])<i)l++;
    23         t=q[l];
    24         f[i]=f[t]+(long long)(i-t)*(i-t-1)/2+a[i];
    25         while(l<r&&slope(q[r-1],q[r])>slope(q[r],i))r--;
    26         q[++r]=i;
    27     }
    28     printf("%lld",f[n]);
    29     return 0;
    30 }
    View Code

    7.【bzoj3437】小P的牧场

    题意:见原题

    分析:无

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=1000050;
     6 long long n,a[N],b[N],sum[N],num[N],f[N],q[N],l=0,r=0;
     7 int read()
     8 {
     9     int x=0,f=1;char c=getchar();
    10     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    11     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    12     return x*f;
    13 }
    14 double slope(long long k,long long j)
    15 {
    16     return (double)(f[j]-sum[j+1]+num[j+1]*n-f[k]+sum[k+1]-num[k+1]*n)/(double)(num[j+1]-num[k+1]);
    17 }
    18 int main()
    19 {
    20     n=read();
    21     for(int i=1;i<=n;i++)a[i]=read();
    22     for(int i=1;i<=n;i++)b[i]=read();
    23     for(long long i=1;i<=n;i++)
    24     {
    25         sum[i]=sum[i-1]+(long long)b[i-1]*(n-i+1);
    26         num[i]=num[i-1]+b[i-1];
    27     }
    28     for(long long i=1;i<=n;i++)
    29     {
    30         while(l<r&&slope(q[l],q[l+1])<i)l++;
    31         long long t=q[l];
    32         f[i]=f[t]+sum[i]-sum[t+1]-(num[i]-num[t+1])*(n-i)+a[i];
    33         while(l<r&&slope(q[r],i)<slope(q[r-1],q[r]))r--;
    34         q[++r]=i;
    35     }
    36     printf("%lld
    ",f[n]);
    37     return 0;
    38 }
    View Code

    【背包dp】

    〖相关题目

    1.【codeforces914H】Ember and Storm's Tree Game

    题意:Zsnuoの博客

    分析:Zsnuoの博客

     1 #include<cstdio>
     2 #include<algorithm> 
     3 #include<cstring>
     4 #define LL long long
     5 using namespace std;
     6 const int N=205;
     7 int n,d,mod;
     8 LL ans,sum[N],c[N][N],f[N][N];
     9 int main()
    10 {
    11     scanf("%d%d%d",&n,&d,&mod);
    12     for(int i=0;i<=n;i++)c[i][0]=1;
    13     for(int i=1;i<=n;i++)
    14         for(int j=1;j<=i;j++)
    15             c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
    16     sum[1]=1;f[1][0]=1;
    17     for(int i=2;i<=n;i++)
    18     {
    19         for(int j=1;j<=d;j++)
    20             for(int k=1;k<i;k++)
    21                 f[i][j]=(f[i][j]+f[i-k][j-1]*sum[k]%mod*c[i-2][k-1]%mod)%mod;
    22         for(int j=1;j<=d-1;j++)
    23             sum[i]=(sum[i]+f[i][j])%mod;
    24     }
    25     for(int i=0;i<=n-1;i++)
    26         for(int j=0;j<=d;j++)
    27             for(int k=0;j+k<=d;k++)
    28                 if(k!=1)ans=(ans+f[i+1][j]*f[n-i][k]%mod)%mod;
    29     printf("%lld",2*n*(n-1)*ans%mod);
    30     return 0;
    31 }
    View Code

    【树形dp】

    〖相关题目

    1.【SRM-05 B】无题?

    题意:给定一棵树,选定一些特殊点,若点集中存在两个点有边直接相连,则将该点集计入方案,求总方案数。

    分析:Zsnuoの博客

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #define ll long long
     5 using namespace std;
     6 const int N=1e5+5;
     7 const int mod=1e9+7;
     8 int n,x,y,cnt,head[N];
     9 struct edge{int to,next;}e[N*2];
    10 ll ansn=1,dp[N][2];
    11 int read()
    12 {
    13     int x=0,f=1;char c=getchar();
    14     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    15     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    16     return x*f;
    17 }
    18 void ins(int u,int v){cnt++;e[cnt].to=v;e[cnt].next=head[u];head[u]=cnt;}
    19 void solve(int x,int fa)
    20 {
    21     dp[x][1]=dp[x][0]=1;
    22     for(int i=head[x];i;i=e[i].next)
    23     {
    24         int to=e[i].to;
    25         if(to==fa)continue;
    26         solve(to,x);
    27         dp[x][0]=(dp[to][0]+dp[to][1])%mod*dp[x][0]%mod;
    28         dp[x][1]=dp[to][0]*dp[x][1]%mod;
    29     }
    30 }
    31 int main()
    32 {
    33     n=read();
    34     for(int i=1;i<n;i++)
    35     {
    36         x=read();y=read();
    37         ins(x,y);ins(y,x);
    38     }
    39     solve(1,0);
    40     for(int i=1;i<=n;i++)ansn=(ansn*2)%mod;
    41     printf("%lld",((ansn-dp[1][0]-dp[1][1])%mod+mod)%mod);
    42     return 0;
    43 }
    View Code

    2.【codeforces627D】Preorder Test

    题意:给定一棵n个节点的无根树,求出dfs序的前k个结点权值最小值的最大值。

    分析:godspeedkakaの博客

     1 #include<cstdio>
     2 #include<algorithm> 
     3 #include<cstring>
     4 #define LL long long
     5 using namespace std;
     6 const int N=2e5+5;
     7 int n,k,cnt,u,v;
     8 int a[N],w[N],sz[N],first[N],dp[N],up[N]; 
     9 bool flag;
    10 struct edge{int to,next;}e[N*2];
    11 int read()
    12 {
    13     int x=0,f=1;char c=getchar();
    14     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    15     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    16     return x*f;
    17 }
    18 void ins(int u,int v){e[++cnt]=(edge){v,first[u]};first[u]=cnt;}
    19 void dfs1(int x,int fa)
    20 {
    21     sz[x]=1;
    22     for(int i=first[x];i;i=e[i].next)
    23     {
    24         int to=e[i].to;
    25         if(to==fa)continue;
    26         dfs1(to,x);sz[x]+=sz[to];w[x]+=w[to];
    27     }
    28 }
    29 void dfs2(int x,int fa,int m)
    30 {
    31     int mx1=0,mx2=0,tot=0;
    32     for(int i=first[x];i;i=e[i].next)
    33     {
    34         int to=e[i].to;
    35         if(to==fa)continue;
    36         if(w[x]-w[to]==sz[x]-sz[to]&&up[x])up[to]=1;
    37         dfs2(to,x,m);
    38         if(a[to]<m)continue;
    39         if(sz[to]==w[to])tot+=sz[to];
    40         else
    41         {
    42             if(dp[to]>mx1)mx2=mx1,mx1=dp[to];
    43             else if(dp[to]>mx2)mx2=dp[to];
    44         }
    45     }
    46     if(a[x]<m)return;
    47     if(tot+mx1+mx2+up[x]*(n-sz[x])+1>=k)flag=true;
    48     dp[x]=tot+mx1+1;
    49 }
    50 bool check(int x)
    51 {
    52     memset(dp,0,sizeof(dp));
    53     memset(up,0,sizeof(up));
    54     for(int i=1;i<=n;i++)w[i]=(a[i]>=x);
    55     dfs1(1,-1);
    56     up[1]=1;flag=false;
    57     dfs2(1,-1,x);
    58     return flag;
    59 }
    60 int main()
    61 {
    62     n=read();k=read();
    63     for(int i=1;i<=n;i++)a[i]=read();
    64     for(int i=1;i<n;i++)
    65     {
    66         u=read();v=read();
    67         ins(u,v);ins(v,u);
    68     }
    69     int l=0,r=1e6,mid,ans;
    70     while(l<=r)
    71     {
    72         mid=(l+r)>>1;
    73         if(check(mid))l=mid+1,ans=mid;
    74         else r=mid-1;
    75     }
    76     printf("%d",ans);
    77     return 0;
    78 }
    View Code

    【数位dp】

    〖相关题目

    1.【计蒜之道2017复赛E】商汤智能机器人

    题意:二维平面,起点在(0,0), 假如当前在(x,y),则下一步可以走到(x+1,y+1)或(x+1,y-1)或(x+2,y),求从(0,0)走到(X,Y)的方案数。

    分析:sakitsの博客

     1 #include<cstdio>
     2 #include<algorithm> 
     3 #include<cstring>
     4 #define LL long long
     5 using namespace std;
     6 const int N=1e5+5;
     7 const int mod=1e5+3;
     8 LL x,y,n,tmp,na,nb;
     9 int fac[N],inv[N],a[15],b[15],f[15],g[15];
    10 int power(int a,int b)
    11 {
    12     int ans=1;
    13     while(b)
    14     {
    15         if(b&1)ans=1ll*ans*a%mod;
    16         a=1ll*a*a%mod;b>>=1;
    17     }
    18     return ans;
    19 }
    20 int C(int n,int m){return n<m?0:1ll*fac[n]*inv[m]%mod*inv[n-m]%mod;}
    21 void Mod(int& a,int b){a+=b;if(a>=mod)a-=mod;}
    22 int main()
    23 {
    24     scanf("%lld%lld",&x,&y);
    25     if((x+y)&1||x<y){printf("0");return 0;}
    26     fac[0]=1;
    27     for(int i=1;i<mod;i++)fac[i]=1ll*fac[i-1]*i%mod;
    28     inv[mod-1]=power(fac[mod-1],mod-2);
    29     for(int i=mod-1;i>=1;i--)inv[i-1]=1ll*inv[i]*i%mod;
    30     n=(x+y)>>1;
    31     tmp=x;while(tmp)a[++na]=tmp%mod,tmp/=mod;
    32     tmp=n;while(tmp)b[++nb]=tmp%mod,tmp/=mod;
    33     f[1]=1;
    34     for(int i=1;i<=na;i++)
    35     {
    36         if(f[i])
    37         {
    38             for(int j=0;j<mod;j++)
    39                 if(j<=a[i])Mod(f[i+1],1ll*f[i]*C(b[i],j)%mod*C(a[i]-j,b[i])%mod);
    40                 else Mod(g[i+1],1ll*f[i]*C(b[i],j)%mod*C(a[i]-j+mod,b[i])%mod);
    41         }
    42         if(g[i])
    43         {
    44             for(int j=0;j<mod;j++)
    45                 if(j<a[i])Mod(f[i+1],1ll*g[i]*C(b[i],j)%mod*C(a[i]-j-1,b[i])%mod);
    46                 else Mod(g[i+1],1ll*g[i]*C(b[i],j)%mod*C(a[i]-j-1+mod,b[i])%mod);
    47         }
    48     }
    49     printf("%d",f[na+1]);
    50     return 0;
    51 }
    View Code

                                                                                                                                                                                                                           

  • 相关阅读:
    Linux操作系统(二)
    匿名函数和内置函数
    BeautifulSoup
    Robots协议
    列表和生成器表达式
    迭代器
    排序总结
    图论专题笔记
    Trie树的二三事QWQ
    二分答案经典入门题:)
  • 原文地址:https://www.cnblogs.com/zsnuo/p/8572425.html
Copyright © 2011-2022 走看看