2匹のウサギHDU - 4745(最長回文配列、間隔DP)

長い長い前に、森の中で2匹のウサギトムとジェリーが住んでいました。晴れた日の午後には、彼らはいくつかの石でゲームをプレイすることを計画しました。そこ地面にn個の石だったし、彼らは時計回りのリングとして配置しました。すなわち、最初の石が第二石とn番目の石に隣接した、第二石が最初石および第三石に隣接している、などと言うことです。i番目の石の重量は愛です。

ウサギは他に一石から飛び降り。トムは常に時計回りに飛び込んだ、とジェリーは常に反時計回りに跳ね上がりました。

初めに、ウサギは、両方の石を選択して、その上に立っています。そして、各ターンで、トムはそれ自体で強化し、それに跳ね上がった、とジェリーはトムと同じことを行う必要がありますが、ジャンプの方向が反時計回りであるされていない石を選択する必要があります。

いくつかの未知の理由で、任意の時点で、2匹のウサギが立った上で2つの石の重さは同じでなければなりません。また、任意のウサギは、それ自体で強化されてきた石を飛び越えることができませんでした。トムは第二石に立っていた言い換えれば、それは第三の石またはN-石から4番目の石に最初の石からジャンプすることができません。

2匹のウサギが同時に同じ石の上に立つために、全体のプロセスの間に、それはOKだったことに注意してください。

今、彼らは、彼らが最適な戦略に従うならば、彼らは遊ぶことができる最大のターンを知りたいです。
入力は、
入力は最大で20のテストケースが含まれています。
各テストケースのために、最初の行は、石の数を表す整数nを含んでいます。
次の行は含まnは整数は、スペースで区切られた、i番目の整数は、i番目の石の重量を意味する愛。(1 <= N <= 1000、1 <=は、<= 1000 AI)の
入力端と、N = 0
出力
各テストケースについては、最大ターンを示す整数を印刷します。
サンプル入力
1
1
4
1 2 1
6
2 1 1 2 1 3
0
出力例
1
4
5

ヒント
第二のケースでは、トムの経路は、ジェリーの1、2、3、4、および経路は、2 1、4、3である
第三のケースでは、トムの経路は1,2,3であり、 4,5とジェリーのパスが4,3,2,1,5です。

質問の意味:
リング。二つは、(マルチグリッドとすることができる)単一方向ホップバニー、それ自身の方向で前のノードを超えることはできません。毎回同じ量及びノード必要値。どのように多くのラウンドは、要件にまでジャンプすることができます。
アイデア:
本質は最長の回文配列です。長い2匹のウサギにおける対応するノードとして回文配列としては、完全なチェーンにジャンプすることができます。
DP [i] [j]の定義は、jへの最長の回文配列Iです。
答えが最大である{DP [1]〜[I ] + DP [I + 1] [J]}。

また、チェーンが倍増することができます。答えとなる
DPを[I] [N-I + - 。1]
DP [I] [N-I + - 2]。+ 1(以下、出発点として、その点ながら2匹のウサギ)

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

int dp[2005][2005];
int a[2005];

int main()
{
    int n;
    while(~scanf("%d",&n) && n)
    {
        for(int i = 1;i <= n;i++)
        {
            scanf("%d",&a[i]);
            dp[i][i] = dp[i + n][i + n] = 1;
            a[i + n] = a[i];
        }
        
        for(int len = 2;len <= 2 * n;len++)
        {
            for(int i = 1;i + len - 1 <= 2 * n;i++)
            {
                int j = i + len - 1;
                if(a[i] == a[j])dp[i][j] = dp[i + 1][j - 1] + 2;
                else dp[i][j] = max(dp[i + 1][j],dp[i][j - 1]);
            }
        }
        
        int ans = 0;
        for(int i = 1;i <= n;i++)
        {
            ans = max(ans,dp[i][i + n - 1]);
            ans = max(ans,dp[i][i + n - 2] + 1);
        }
        printf("%d\n",ans);
    }
    return 0;
}
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

int dp[1005][1005];
int a[1005];

int main()
{
    int n;
    while(~scanf("%d",&n) && n)
    {
        for(int i = 1;i <= n;i++)
        {
            scanf("%d",&a[i]);
            dp[i][i] = 1;
        }
        for(int len = 1;len <= n;len ++)
        {
            for(int i = 1,j = len;j <= n;i++,j++)
            {
                int x = 2;
                if(i == j)x = 1;
                
                if(a[i] == a[j])dp[i][j] = dp[i + 1][j - 1] + x;
                else dp[i][j] = max(dp[i][j - 1],dp[i + 1][j]);
            }
        }
        int ans = 0;
        for(int i = 1;i <= n;i++)
        {
            ans = max(dp[1][i] + dp[i + 1][n],ans);
        }
        printf("%d\n",ans);
    }
    return 0;
}
公開された676元の記事 ウォン称賛18 ビュー30000 +

おすすめ

転載: blog.csdn.net/tomjobs/article/details/104230368