POJ 1187-陨石的秘密(DP)

用d[i][j][u][v]表示i个{},j个[],u个(),深度为v的序列数,根据最后一个子括号(就是最后一个反括号对应的正括号范围内的括号)分类计数。


最后一个子括号可能深度小于v,此时前面的括号深度必须为v,最后一个子括号深度也可能等于v,此时前面的括号深度可以小于或等于v。

用sum[i][j][u][v]表示i个{},j个[],u个(),深度小于等于v的序列数。没递推完i,j,u后,立即计算相应的sum[i][j][u][0…D]的值。


枚举最后一个子括号内有哪些括号完成递推。


#include<stdio.h>
#include<stdlib.h>
int d[12][12][12][32];
int sum[12][12][12][32];
int main(void)
{
	int i,j,u,v,p,q,n,m,vi,vj,vu,sump;
	scanf("%d%d%d%d",&q,&n,&m,&p);
	d[0][0][0][0]=1;
	sum[0][0][0][0]=1;
	for(i=0;i<=q;i++)
	{
		for(j=0;j<=n;j++)
		{
			for(u=0;u<=m;u++)
			{
				for(v=1;v<=p;v++)
				{
					if(i+j+u<v)
					{
						d[i][j][u][v]=0;
					}
					else
					{
						if(i!=0)
						{
							sump=d[i-1][j][u][v-1];
						}
						else if(j!=0)
						{
							sump=d[0][j-1][u][v-1];
						}
						else if(u!=0)
						{
							sump=d[0][0][u-1][v-1];
						}
						else
						{
							sump=0;
						}
						for(vi=0;vi<=i;vi++)
						{
							for(vj=0;vj<=j;vj++)
							{
								for(vu=0;vu<=u;vu++)
								{
									if((vi+vj+vu!=0)&&(vi+vj+vu!=i+j+u))
									{
										if(vi!=0)
										{
											if(v>=2)
											{
												sump=(sump+sum[vi-1][vj][vu][v-2]*d[i-vi][j-vj][u-vu][v])%11380;
											}
											sump=(sump+d[vi-1][vj][vu][v-1]*sum[i-vi][j-vj][u-vu][v])%11380;
										}
										else if(vj!=0)
										{
											if(v>=2)
											{
												sump=(sump+sum[0][vj-1][vu][v-2]*d[i][j-vj][u-vu][v])%11380;
											}
											sump=(sump+d[0][vj-1][vu][v-1]*sum[i][j-vj][u-vu][v])%11380;
										}
										else
										{
											if(v>=2)
											{
												sump=(sump+sum[0][0][vu-1][v-2]*d[i][j][u-vu][v])%11380;
											}
											sump=(sump+d[0][0][vu-1][v-1]*sum[i][j][u-vu][v])%11380;
										}
									}
								}
							}
						}
						d[i][j][u][v]=sump;
					}
				}
				for(v=1;v<=p;v++)
				{
					sum[i][j][u][v]=(sum[i][j][u][v-1]+d[i][j][u][v])%11380;
				}
			}
		}
	}
	printf("%d\n",d[q][n][m][p]);
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值