原题 [NOIP2003]加分二叉树
题目大意:输入一棵树的中序遍历,定义一棵子树的得分为其左子树的加分×右子树的加分+根的分数。求最大得分及先序遍历
注意:5、区间内选取根两端点要取到
思路参考 代码参考
#include
#include
#include
using namespace std;
int n,a[31];
long long dp[27][27],r[27][27];//dp[i][j]表示中序遍历序列从i到j的最高得分
void print(int i,int j)
{
if (i>j)
return ;
cout<>n;
memset(dp,0,sizeof(0));
for (i=1;i<=n;i++)
{
cin>>a[i];
dp[i][i]=a[i];
dp[i][i-1]=1;dp[i+1][i]=1;//防止左子树(或右子树)为空的情况(虽然这个意义上的dp不存在)
r[i][i]=i;//初始为叶子节点(每个都为根)
}
for (i=2;i<=n;i++)//区间长度
for (j=1;j<=n-i+1;j++)//区间起点,注意截止是n-i+1
for (k=j;k<=j+i-1;k++)//取区间内一点为root,注意必须两头都要取到!
if (dp[j][j+i-1]
题目链接:
题目大意:n堆石子围成圈,每次合并得分为合并后石子的重量,求合并成一堆石子后的最大得分和最小得分
思路: 思路参考
1、将前n-1堆石子挪到第n堆后面,则考虑合并2n-1堆石子
2、dp[i][j]是将第i到第j堆合并为一堆的总得分
注意:3、最终结果还需一重循环,是dp[i][i+n-1]的最大值
#include
#include
#include
using namespace std;
int n,a[101];
int dp[201][201],fp[201][201];//dp[i][j]将第i到第j堆合并为一堆的总得分
int sum[201];//保存第1到第i堆石子的和
int main()
{
int len,j,k,i;
cin>>n;
memset(dp,0,sizeof(dp));
memset(fp,0x3f,sizeof(fp));
memset(sum,0,sizeof(sum));
for (i=1;i<=n;i++)
{
cin>>a[i];
dp[i][i]=0;fp[i][i]=0;//一堆没有合并,初始为1
sum[i]=sum[i-1]+a[i];
}
for (i=1;i<=n-1;i++)//将前n-1堆石子挪到第n堆后面
{
dp[n+i][n+i]=0;fp[n+i][n+i]=0;
sum[n+i]=sum[n+i-1]+a[i];
}
for (len=2;len<=n;len++)//区间长度
for (i=1;i<=2*n-1;i++)
{
j=len+i-1;
if (j>2*n-1) break;
for (k=i;k
Brackets 括号匹配问题
题意:给出一个的只有'(',')','[',']'四种括号组成的字符串,求最多有多少个括号满足题目里所描述的完全匹配。
·空串是完全匹配
·若s是完全匹配,则(s)和[s]是;若a和b是完全匹配,则ab是
思路:dp[i][j]表示[i,j]里最大完全匹配数。
//不知道对不对,没找到可以评测的oj,哪位小伙伴知道可以告知我一声谢谢!!
#include
#include
#include
#include
using namespace std;
int dp[101][101];
int main()
{
string s;
int len,j,k,i,n;
while(cin>>s)
{
if (s=="end")
break;
n=s.length();
s=" "+s;//s[1...n]
memset(dp,0,sizeof(dp));
for (len=2;len<=n;len++)
for (i=1;i<=n;i++)
{
j=len+i-1;
if (j>n) break;
if ((s[i]=='(' && s[j]==')') ||(s[i]=='[' && s[j]==']'))//若匹配
dp[i][j]=dp[i+1][j-1]+2;
for (k=i+1;k
括号匹配变形及输出:百练 1141:Brackets Sequence
题目大意:找出以输入序列为子序列的最短合法序列。如 ([(] 的答案是 ()[()]
思路解释: 思路参考c[i][j]为输入序列从下标i到下标j的断开位置,如果没有断开则为-1
代码理解有点困难,我举个栗子:‘([))’,则dp[1][3]=1,dp[1][4]=2,c[1][4]=3,而dp[2][3]=2,即'[)',dp[1][4]==dp[2][3],则不会进入c[i][j]=-1。而dp[1][3]在k的遍历中得3,dp[2][2]=1 含义是,从内层开始找,最先找到的不匹配是解决的最小子问题(子问题解决了后面的不匹配也就解决了),即所求的最少的增加括号数 2、匹配后加判断dp[i][j]>dp[i+1][j-1]才能确定c[i][j]=-1 AC代码:
1、初始化dp[i][i]=1
#include