[HDU] 4512 吉哥系列故事——完美队形I(有点dp味道的递归模拟)

题目连接:

http://acm.hdu.edu.cn/showproblem.php?pid=4512

方法:F(a,b)为在a,b段间能获得找出的最多人数,则原问题的解为:

F(1,n)=Max({F'(i,n)|  1=<i<=n  })

对于每一个F'(i,n),计算过程如下:

首先计算出在i到n段,等于第i个数的最后的值的位置j,根据i和j的关系,若i==j 直接返回1,如i==j-1,返回2,其他情况, 在i+1 和 j-1这段中,枚举每一个大于第i个数的数的位置p,递归去计算每一个F'(p,j-1),取出最大的一个加上2得到一个F'(i,n);而递归计算每一个F'(p,j-1)的方法和计算每一个F'(i,n)一样。

代码:

#include <iostream>
#include <queue>
#include <map>
#include<algorithm> 
using namespace std;
int nums[201];
int dp[202][202];
int n;
int found(int x,int st,int ed=n)
{
	if(dp[st][ed]!=-1)
		return dp[st][ed];
	 if(st==ed)
		 return 1;
	 int newEnd;
	 for(int i=ed;i>=st;i--)
	 {
		 if(nums[st]==nums[i])
		 {
			 newEnd=i;
			 break;
		 }
	 }
	 int px = (newEnd==st  ? 1:2);
	 int max=0;
	 for(int i=st+1;i<=newEnd-1;i++)
	 {
		 if(nums[i]>nums[st])
		 {
			 int re = found(0,i,newEnd-1);
			 max = max>re ? max:re;
		 }
	 }
	 return dp[st][ed]=px+max;
}
int main()
{
    
    int tc = 0;
    scanf("%d",&tc);
    while(tc>0)  
    {
		memset(dp,-1,sizeof(dp));
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&nums[i]);
        int sum=0,end=n,max=0;
        for(int i=1;i<=n;i++)
		{
			int re = found(i,i,n);
			max =max > re ? max:re;
		}
        cout<<max<<endl;
        tc--;
    }
    return 0;
}

 感想:不要看漏条件,题目要求左到中是递增的,否则结果会是超时再WA,

原文地址:https://www.cnblogs.com/kbyd/p/3229532.html