hdu 4745 Two Rabbits(带思维的DP)

Two Rabbits

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 800    Accepted Submission(s): 419


Problem Description
Long long ago, there lived two rabbits Tom and Jerry in the forest. On a sunny afternoon, they planned to play a game with some stones. There were n stones on the ground and they were arranged as a clockwise ring. That is to say, the first stone was adjacent to the second stone and the n-th stone, and the second stone is adjacent to the first stone and the third stone, and so on. The weight of the i-th stone is ai.

The rabbits jumped from one stone to another. Tom always jumped clockwise, and Jerry always jumped anticlockwise.

At the beginning, the rabbits both choose a stone and stand on it. Then at each turn, Tom should choose a stone which have not been stepped by itself and then jumped to it, and Jerry should do the same thing as Tom, but the jumping direction is anti-clockwise.

For some unknown reason, at any time , the weight of the two stones on which the two rabbits stood should be equal. Besides, any rabbit couldn't jump over a stone which have been stepped by itself. In other words, if the Tom had stood on the second stone, it cannot jump from the first stone to the third stone or from the n-the stone to the 4-th stone.

Please note that during the whole process, it was OK for the two rabbits to stand on a same stone at the same time.

Now they want to find out the maximum turns they can play if they follow the optimal strategy.
 

Input
The input contains at most 20 test cases.
For each test cases, the first line contains a integer n denoting the number of stones.
The next line contains n integers separated by space, and the i-th integer ai denotes the weight of the i-th stone.(1 <= n <= 1000, 1 <= ai <= 1000)
The input ends with n = 0.
 

Output
For each test case, print a integer denoting the maximum turns.
 

Sample Input
   
   
   
   
1 1 4 1 1 2 1 6 2 1 1 2 1 3 0
 

Sample Output
   
   
   
   
1 4 5
Hint
For the second case, the path of the Tom is 1, 2, 3, 4, and the path of Jerry is 1, 4, 3, 2. For the third case, the path of Tom is 1,2,3,4,5 and the path of Jerry is 4,3,2,1,5.
 

Source
2013 ACM/ICPC Asia Regional Hangzhou Online
 

Recommend
liuyiding   |   We have carefully selected several similar problems for you:   4846  4845  4844  4843  4842 
 

题意:

给你围成一圈的n(N<=1000)个石头的重量。顺时针给出。现在有两只选两个石头站上去。两个兔子可以站在同一块石头上。然后他们一个按顺时针一个按逆时针跳。每一步他们只能跳到重量相同的石头上(可以是同一块石头)。但自己站过的石头不能再战也不能越过。也就是最多跳一圈。现在问他们最多能进行多少步。

思路:

对于环形问题根据经验可以把序列复制两段来处理。由于一个兔子往左跳一个兔子往右跳。且它们所站的石头值要一样。不管他们初始位置如何他们所站过的石头一定会组成一个回文序列。那么问题就转化为求环形序列的最长子序列了。对于求线性序列的回文子序列很简单。

if(val[i]==val[j])

    dp[i][j]=dp[i+1][j-1]+2;

else

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

dp[i][j]表示[i,j]这段序列所能组成回文子序列的最大长度。至于方程为什么是这样的呢?当val[i]==val[j]的时候毫无疑问第i个和第j个位置的值都能加入到最长回文子序列中。对于val[i]!=val[j]的情况。i,j至多只能选一个位置的值。如果两个都选的话就不满足回文的条件了。所以只能从dp[i][j-1](不选j可选i).dp[i+1][j](不选i可选j)两个较大的转移。对于环形的我们的方程还是不变。

有两种方法。

1.将序列复制两倍。这样按照上面线性的方程算出dp值,关键是最大的步数怎么确定。两个兔子可以站在最长序列的两端然后对着跳。这时步数就为序列的长度。这时我们枚举一只兔子的起点i.由于不能一圈另一只兔子最多站到i+n-1的位置。所以取dp[i][i+n-1]的最大值即可。还有种可能就是两只兔子站在同一块石头上。这时由兔子于站在回文序列的两端。所以起点和终点值相同.就要利用到dp[i][i+n]-1(一个点被重复计算)。

详细见代码:

#include <iostream>
#include<stdio.h>
using namespace std;
const int maxn=2010;
int arr[maxn<<1],dp[maxn][maxn];
int main()
{
    int i,j,n,m,ans;

    while(scanf("%d",&n),n)
    {
        m=2*n,ans=1;
        for(i=0;i<n;i++)
            scanf("%d",&arr[i]),arr[n+i]=arr[i];
        for(i=0;i<m;i++)
            dp[i][i]=1;
        for(i=m-1;i>=0;i--)
            for(j=i+1;j<m;j++)
                {
                    if(arr[i]==arr[j])
                        dp[i][j]=dp[i+1][j-1]+2;
                    else
                        dp[i][j]=max(dp[i][j-1],dp[i+1][j]);
                }
        for(i=0;i<n;i++)
            ans=max(ans,dp[i][i+n-1]),ans=max(ans,dp[i][i+n]-1);
        printf("%d\n",ans);
    }
    return 0;
}
方法2:

不用把序列增倍。这个正在研究。


你可能感兴趣的:(c,算法,ACM)