NDK 1330 考验

15 篇文章 0 订阅
9 篇文章 0 订阅

问题描述:

 大家知道,黄药师不仅武功高超,而且酷爱音乐和诗歌。看到桃花岛来了个新客人,而且  不是靠真武功进来的,就准备为难为难你。
 他写了一首N行诗句的诗歌,美中不足的是这些诗句并不押韵,黄药师非常想遵循古诗的  押韵。诗歌被分为若干段,每段都是四行诗。每一句诗都有一个韵脚,假如A和B表示两种  不同的韵脚,每段四行诗的韵脚只可能是 “AABB”, “ABAB”, “ABBA” 和“AAAA”中的一种。
 黄药师将诗句的韵脚都编了号,具有相同编号的句子代表有相同的韵脚。现在,黄药师想  删掉一些句子,使得剩下的都是遵循押韵规则的四行诗,而且不允许改变诗句的顺序。
 现在就问你:如何找出满足条件最长的诗歌?

数据输入:

 第1行为一个整数N(1 <= N <= 4000),代表黄药师写的诗歌的句子数。
 第2行为N个整数,分别表示每一行诗的韵脚,这些数字都是不超过10^9的正数,每个数之  间用1个空格隔开。

结果输出:

  一行一个整数k,为黄药师最多能够得到的四行诗个数。

样例:

 15
 1 2 3 1 2 1 2 3 3 2 1 1 3 2 2
3

核心思想:

 有两个方法:动规(没看懂),贪心(是个规律,依旧不懂)

//动规
var
  n:longint;
  a:array[0..4001] of longint;
  f:array[0..4001] of longint;
  can:array[0..4001,0..4001] of boolean;
function max(x,y:longint):longint;
begin
  if x>y then exit(x) else exit(y);
end;
procedure init;
var
  i,j:longint;
  flag:boolean;
begin
  readln(n);
  for i:=1 to n do read(a[i]);
  for i:=1 to n do
  begin
    flag:=false;
    for j:=i+1 to n do
      if (flag) or (a[i]=a[j]) then
      begin
        can[i,j]:=true;
        flag:=true;
      end
      else can[i,j]:=false;
  end;
end;
function check(ed,st:longint):boolean;
var
  i:longint;
begin
  for i:=st to ed do
    if can[i,ed] then exit(true);
  exit(false);
end;
procedure main;
var
  i,j:longint;
  flag:boolean;
begin
  fillchar(f,sizeof(f),0);
  for i:=1 to n do
  begin
    f[i]:=f[i-1];
    flag:=false;
    for j:=i-1 downto 1 do
    begin
      if a[i]=a[j] then flag:=true;
      if i-j+1<4 then continue;
      if (a[i]<>a[j]) and (flag) and (can[j,i-1]) then
      begin
        f[i]:=max(f[i],f[j-1]+1);
        break;
      end;
      if (a[i]=a[j]) and (check(i-1,j+1)) then
      begin
        f[i]:=max(f[i],f[j-1]+1);
        break;
      end;
    end;
  end;
  writeln(f[n]);
end;
begin
  init;
  main;
//===========================================================
//贪心
var
 i,s,k,m,n,z:longint;
 a:array[0..10000] of longint;
begin
 readln(n);
 for i := 1 to n do
 begin
  read(s);
  if (a[s]>m) and (k<>s) then
  begin
   inc(z);
   if not odd(z) then m := i;
   k := s;
  end
   else
  begin
   if k=s then k := 0;
   a[s] := i;
  end;
 end;
 writeln(z div 2);
end.
题目来源:NDK 1330 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值