zoukankan      html  css  js  c++  java
  • [HDU4745] Two Rabbits (区间DP)

    题目链接


    Solution

    区间DP。
    显然是统计最长的回文序列.
    状态定义:
    (f[i][j]) 表示 (i)(j) 的最长回文序列长度.
    状态转移:

    1. (s[i] eq s[j])
      那么此时 (f[i][j]) 即为(f[i][j-1]),(f[i+1][j])种较大的那个.
      但由于 (i+1->j-1)的我们明显重复统计了,所以方程即为:

    [f[i][j]=max(f[i+1][j],f[i][j-1]) ]


    2. $s[i]=s[j]$ 此时考虑,对于 $i+1$ 到 $j-1$ 中的回文序列,我们都可以把 $s[i]$和$s[j]$ 加在两边.长度多2. 所以此时方程即为: $$f[i][j]=f[i+1][j-1]+2$$

    最后还要考虑是否从同一起点出发.
    若从同一起点出发,那么答案即为 (f[i][i+n-2]+1).
    否则就为 (f[i][i+n-1])

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1008;
    int f[maxn][maxn];
    int n,t,s[maxn];
    int ans;
    
    int main()
    {
    	while(1)
    	{
    		scanf("%d",&n);
    		if(n==0)return 0;
    		ans=1;
    		memset(f,0,sizeof(f));
    		for(int i=0;i<n;i++)
    		{
    			scanf("%d",&s[i]);
    			s[i+n]=s[i];
    		}
    		for(int i=0;i<2*n;i++)
    		{
    			f[i][i]=1;
    			if(i>0){
    			if(s[i]==s[i-1])
    			f[i-1][i]=2;
    			else f[i-1][i]=1;	
    			}
    		}
    		for(int len=3;len<=n;len++)
    		for(int l=0;l<=2*n-len;l++)
    		{
    			int r=l+len-1;
    			if(s[l]==s[r])
    			f[l][r]=(f[l+1][r-1]+2);
    			else 
    			f[l][r]=max(f[l][r-1],f[l+1][r]);
    			ans=max(ans,f[l][r]);
    		}
    		
      		for (int i=0;i<=n;i++)
      		{
          		ans=max(ans,f[i][i+n-1]);
          		ans=max(ans,f[i][i+n-2]+1);
      		}	
    		printf("%d
    ",ans);
    	}		
    }
    
  • 相关阅读:
    flask_第一个程序
    Web框架_MVC vs MVT
    python_使用qrcode生成二维码
    HDU 4641
    SPOJ NSUBSTR
    SPOJ LCS2 多个串的最长公共子串
    SPOJ LCS 后缀自动机找最大公共子串
    POJ 1509 循环同构的最小表示法
    HDU 4821 字符串hash
    SPOJ GSS1 静态区间求解最大子段和
  • 原文地址:https://www.cnblogs.com/Kv-Stalin/p/9464920.html
Copyright © 2011-2022 走看看