UVALive 3516 Exploring Pyramids 区间dp+计数原理

题目链接:点击打开链接

给定多叉树的先序遍历结果,求多叉树的同构数

思路:区间dp

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Scanner;

public class Main {
	int min(int a,int b){return a>b?b:a;}
	int max(int a,int b){return a>b?a:b;}
	long min(long a,long b){return a>b?b:a;}
	long max(long a,long b){return a>b?a:b;}
	int abs(int x){return x>0?x:-x;}
	static long mod = 1000 * 1000 * 1000;
	static int N = 1005;
	String s;
	long[][] dp = new long[N][N];
	long dfs(int l, int r){
		if(dp[l][r]!=-1)return dp[l][r];
		if(l == r)return dp[l][r] = 1;
		if(s.charAt(l)!=s.charAt(r))return dp[l][r] = 0;
		dp[l][r] = 0;
		for(int i = l+2; i <= r; i++)
			if(s.charAt(i) == s.charAt(l))
				dp[l][r] += dfs(l+1, i-1)*dfs(i,r)%mod;
		dp[l][r] %= mod;
		return dp[l][r];
	}
	void work() {
		while(cin.hasNext()){
			s = cin.next();
			for(int i = 0; i <= s.length(); i++)
				for(int j = i; j <= s.length(); j++)
					dp[i][j] = -1;
			out.println(dfs(0, s.length()-1));
		}
	}

	Main() {
		cin = new Scanner(System.in);
		out = new PrintWriter(System.out);
	}

	public static void main(String[] args) {
		Main e = new Main();
		e.work();
		out.close();
	}

	public Scanner cin;
	public static PrintWriter out;
}
时间: 2024-10-09 14:55:53

UVALive 3516 Exploring Pyramids 区间dp+计数原理的相关文章

UVALive 3516 Exploring Pyramids (区间dp)

#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; #define ll long long const int maxn = 310; const ll mod = 1e9; char s[maxn]; ll dp[maxn][maxn]; ll solve(int i, int j) { if(i == j) retu

uva live 3516 Exploring Pyramids 区间DP

// uva live 3516 Exploring Pyramids 区间DP // // 题目大意: // // 给你一个多叉树,每个节点是一个大写字母,从根节点走,按照先序遍历的 // 原则访问,不能访问则回溯,每次记录一下节点的字符,最后得到一个字符串.现 // 在给你一个字符串,问可能符合条件的多叉树的数量. // // 解题思路: // // 区间DP,我们注意到,从根节点出发,一定会再次回到根节点,那么我们可以设 // d(i,j) 是序列i到j段形成的符合条件的多叉树的数量,则

【区间dp】【记忆化搜索】UVALive - 3516 - Exploring Pyramids

f(i,j)=sum(f(i+1,k-1)*f(k,j) | i+2<=k<=j,Si=Sk=Sj). f(i+1,k-1)是划分出第一颗子树,f(k,j)是划分出剩下的子树. #include<cstdio> #include<cstring> using namespace std; typedef long long ll; #define MOD 1000000000ll char s[310]; ll f[310][310]; int n; ll dp(int

UVA 1362 Exploring Pyramids 区间DP

Archaeologists have discovered a new set of hidden caves in one of the Egyptian pyramids. The decryption of ancient hieroglyphs on the walls nearby showed that the caves structure is as follows. There are n caves in a pyramid, connected by narrow pas

UVALive - 3363 String Compression 区间DP

题目大意:有一串字符串,现在有一种转换规则,如果字符串中出现循环的子串,可以将其转化为 :子串数量(子串) 现在问这个字符串的最短长度 解题思路:区间dp,然后分类讨论,这题的难点是如何再进行缩减 将情况分为两种 一种是区间刚好符合缩减情况的,找出该区间的循环节,看能否继续缩减即可 另一种情况就是普通的区间DP了 #include<cstdio> #include<algorithm> #include<cstring> using namespace std; #de

UVALive 4987---Evacuation Plan(区间DP)

题目链接 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2988 problem Description Flatland government is building a new highway that will be used to transport weapons from its main weapon plan

UVa 1362(LA 3516) Exploring Pyramids

依旧是<训练指南>上的一道例题.思路大致相同,即设有一个序列S(i),S(i+1),S(i+2)...S(j),d[i,j]为所求的解.当S(i)==S(k),i<k<=j 时,说明在k回到根,那么S(i+1)...S(k-1)构成一棵独立的子树(当然也可能并不是子树).那么d[i,j]就要加上d[i+1,k-1]*d[k,j],不断递增k,每遇到一个k,d[i,j]+=d[i+1,k-1]*d[k,j]直到k>j.最后的d[i,j]就是序列S(i)..S(j)的解.那么题目

【区间DP理解】LuoGu P1063/LNSYOJ#139 能量项链/LNSYOJ#157矩阵

这又是本蒟蒻一A的一道水题 题目描述 在MarsMars星球上,每个MarsMars人都随身佩带着一串能量项链.在项链上有NN颗能量珠.能量珠是一颗有头标记与尾标记的珠子,这些标记对应着某个正整数.并且,对于相邻的两颗珠子,前一颗珠子的尾标记一定等于后一颗珠子的头标记.因为只有这样,通过吸盘(吸盘是MarsMars人吸收能量的一种器官)的作用,这两颗珠子才能聚合成一颗珠子,同时释放出可以被吸盘吸收的能量.如果前一颗能量珠的头标记为mm,尾标记为rr,后一颗能量珠的头标记为r,尾标记为nn,则聚合

UVA 1362 - Exploring Pyramids(计数问题+区间DP)

题目链接:1362 - Exploring Pyramids 白书上的例题,思路是对于每个结点,往后遍历分为左右两边子树来考虑,左边的子树为去掉根节点剩下的子树,而右边是要算上根节点的,这样就不会有重复的情况出现,然后根据乘法原理,左右两边情况相乘为总情况数,然后计算这些总和. f[i][j]表示[i,j]结点的情况种数,那么 f[i][j] = sum{f[i + 1][k - 1] * f[k][j]},并且s[i] == s[k] == s[j],因为i, j, k表示的是根节点必须相同.