其他分享
首页 > 其他分享> > 洛谷P5694 [NOI2001] 陨石的秘密

洛谷P5694 [NOI2001] 陨石的秘密

作者:互联网

看完题面的第一反应是暴力

直接四维dp [i,j,k,l]表示深度为i,大中小括号分别为j,k,l时的方案

但发现s=ab这种情况不好处理,还要再枚举一个比d小的深度d'

时间复杂度变成了 D²*L的六次方

想开一个辅助数组g [i,j,k,l]表示深度小于i时的方案数,就可以直接拿出来用了

时间复杂度的问题解决了,但还不知道怎么处理重复计算

比如 [      ]()[        ]

在枚举[      ]时,()[        ]会被计算到

在枚举[      ]()时,[        ]会被计算到

难道是限制括号总长度来限制重复?胡思乱想完,无奈地看了题解

欸,真有趣!

解决重复计算是强制给a最外面匹配括号,就不会出现上述情况了,可以多画几个理解一下

(写到这里,强制转移,强制链接(处理环),最近遇到不止一次了,真是神奇的思想)

时间复杂度是,直接将我设想的辅助数组设为状态

直接四维dp [i,j,k,l]表示深度小于等于i,大中小括号分别为j,k,l时的方案

最后统计答案时用差分的思想dp[d][l1][l2][l3]-dp[d-1][l1][l2][l3]

(似乎做树形dp时有在洛谷遇到,也是计数,大意是给定节点,求二叉树深度为h时的方案数,那题也是直接设求不出来)

嗷,都是很巧妙的思想>_<

 

一些写代码过程中的细节:

1注意大中小括号有区别,不能乱,匹配小括号时要求大中括号为0

2算答案时可能出负数,要加一个mod

3不再是dp [0,0,0,0]=1了,是dp[i,0,0,0]=1,i属于(0,d)

这里是因为后面在枚举过程中,会出现和空串搭配的情况(也就是题面描述的第二种深度计算方式,我们的方程把三种方式都结合在一起了)

比如:

dp[i][j][k][l]=(dp[i][j][k][l]+(dp[i-1][x-1][y][z]*dp[i][j-x][k-y][l-z])%11380)%11380;

会出现x-1,y,z都为0的情况,如果只有dp[0,0,0,0]为1的话就wa了

get:边界的设置跟状态有关,要斟酌一下

4

if(j)
           {
               for(int x=1;x<=j;x++)
                for(int y=0;y<=k;y++)
                 for(int z=0;z<=l;z++)
                  {
                      dp[i][j][k][l]=(dp[i][j][k][l]+(dp[i-1][x-1][y][z]*dp[i][j-x][k-y][l-z])%11380)%11380;
                  }
           }

要保证j首先得不为0,才能强制加,第一次因为这个挂了。

 

code:

#include<bits/stdc++.h>
using namespace std;
int l1,l2,l3,d,dp[31][11][11][11];
int main()
{
    freopen("lys.in","r",stdin);
    
    cin>>l1>>l2>>l3>>d;
    memset(dp,0,sizeof(dp));
    
    for(int i=0;i<=d;i++) dp[i][0][0][0]=1;
    
    for(int i=1;i<=d;i++)
     for(int j=0;j<=l1;j++)
      for(int k=0;k<=l2;k++)
       for(int l=0;l<=l3;l++)
       {
        
          if(j)
           {
               for(int x=1;x<=j;x++)
                for(int y=0;y<=k;y++)
                 for(int z=0;z<=l;z++)
                  {
                      dp[i][j][k][l]=(dp[i][j][k][l]+(dp[i-1][x-1][y][z]*dp[i][j-x][k-y][l-z])%11380)%11380;
                  }
           }
            
          if(k)
             {
                for(int y=1;y<=k;y++)
                 for(int z=0;z<=l;z++)
                  {
                      dp[i][j][k][l]=(dp[i][j][k][l]+(dp[i-1][0][y-1][z]*dp[i][j][k-y][l-z])%11380)%11380;
               }
             }
             
          if(l)
            {
                 for(int z=1;z<=l;z++)
                  {
                      dp[i][j][k][l]=(dp[i][j][k][l]+(dp[i-1][0][0][z-1]*dp[i][j][k][l-z])%11380)%11380;
               }
            }
       }
       
       cout<<(dp[d][l1][l2][l3]-dp[d-1][l1][l2][l3]+11380)%11380;
}

 

标签:洛谷,P5694,int,括号,l2,l3,NOI2001,l1,dp
来源: https://www.cnblogs.com/liyishui2003/p/16182157.html