杭州网赛 two rabbits (hdu 4745)

  算法很简单,问题是,怎么证明,答案是回文序列.

  设a,b走的序列按顺时针是:

  a1 , a2 , a3 , ... , ak

  b1 , b2 , b3 , ... , bk

  考虑端点的2种情况:

   1. a1 b1 ... bk ak

   2. a1 b1 ... ak bk

  对于第一种, 将b1,bk移动到a1,ak ,不会让答案变小, 于是这种情况下的答案为 [i,i+n-1]区间的回文序列长度

  对于情况2, bk对应的下标如果小于a1,那么同样可以进行情况1的操作, 如果 bk的下标>a1那么

  a,b都在两个不想交的区间移动,并且两个区间的总长小于n, 于是答案仍然为 [i,i+n-1]区间的回文序列长度;

  如果bk == a1, 是a,b是从同一个点出发的情况, 答案 为 [i,i+n]区间的回文序列长度-1, 因为起点算了多次,要减1.

  

 1 #include <map>

 2 #include <queue>

 3 #include <ctime>

 4 #include <vector>

 5 #include <cstdio>

 6 #include <string>

 7 #include <cstring>

 8 #include <algorithm>

 9 using namespace std;

10 typedef long long llong;

11 #define ls ((l+r)<<1)

12 #define rs (((l+r)<<1)+1)

13 #define mid ((l+r)>>1)

14 #define maxn 2010

15 

16 int n,a[maxn],f[maxn][maxn];

17 

18 int getvar(int l,int r)

19 {

20     if (l>r) return 0;

21     if (l==r) return f[l][r] = 1;

22     if (f[l][r] != -1) return f[l][r];

23     int res = 0;

24     if (a[l]==a[r]) res = getvar(l+1,r-1)+2;

25     res = max(res,getvar(l+1,r));

26     res = max(res,getvar(l,r-1));

27     return f[l][r] = res;

28 }

29 

30 int main()

31 {

32     freopen("test.txt","r",stdin);

33     while (scanf("%d",&n))

34     {

35         if (!n) break;

36         for (int i=1 ; i<=n ; i++ ) scanf("%d",&a[i]);

37         for (int i=1 ; i<=n ; i++ ) a[i+n] = a[i];

38         int ans = 0;

39         memset(f,-1,sizeof(f));

40         for (int i=1 ; i<=n ; i++ )

41         {

42             int tmp = getvar(i,i+n-1);

43             ans = max(ans,tmp);

44             tmp = getvar(i,i+n) - 1;

45             ans = max(ans,tmp);

46         }

47         printf("%d\n",ans);

48     }

49     return 0;

50 }
View Code

 

你可能感兴趣的:(HDU)