【动归】rainbow与freda染旗

rainbow与freda染旗
From This_poet
背景 Background
Freda:aya Rainbow,怎么没看见你城堡挂旗子呀?
Rainbow:我城堡旗子太难看了肿么办T_T
Freda:lala~那好办,我可以帮你染色呀~
Rainbow:嗯嗯,那就试试吧~ 
描述 Description
Rainbow城堡的旗子是一个有N个基本单位的长条>_<,每个单位都会被染成前m个大写字母当中的一个颜色。可是,Rainbow认为,两个相邻的单位有相同的颜色很难看的说。所以,Rainbow需要改动一些单位的颜色,使得不存在两个相邻的单位颜色相同。当然了,那些被改动的单位改动之后的颜色也是前m个大写字母当中的一个。Rainbow想请你帮忙计算,它最少要改动多少个单位的颜色才能让旗子好看呢?
输入格式 InputFormat
第一行两个整数N、m,表示旗子组成的基本单位数目和颜色的范围。
接下来一行一个长度为N的字符串,字符串的每个字符都是在前m个大写字母的范围内的,表示Rainbow的旗帜。
输出格式 OutputFormat
 一行一个整数表示Rainbow最少改动的单位数目。
样例输入 SampleInput [复制数据]
样例输出 SampleOutput [复制数据]
数据范围和注释 Hint
样例解释:一种改动方法是ABCACA。当然,还可能有别的改动方法。
对于30%的数据,N<=20.
对于100%的数据,N<=10^5,1<=m<=26.
时间限制 TimeLimitation
每个测试点1s



第一次自己做出来一道dp题,虽然很简单。。。虽然还可以用贪心写。。。。。


暴力dp f[i,j]表示 1..i面旗子,第i面旗子染成颜色j的最小染色方案。


显然第i面旗子的方案由第i-1面旗子的方案转移而来


对于第i面旗子有两种决策,不染色,或染成颜色j。


1:第i-1面旗子染成颜色 j1 且 j1<>a[i]


     f[i,a[i]]:=min(f[i,a[i]],f[i-1,j1])


2: 第i-1面旗子染成j1色,第i面旗子染成j色,且(j<>j1)( j<>a[i])


    f[i,j]:=min(f[i,j],f[i-1,j1])+1


最后输出f[n,i]里面最小的值 1<=i<=m

var n,m,i,j,j1,ans:longint;
    a:array[1..100000]of longint;
    f:array[0..100000,1..26]of longint;
    x:char;

function min(a,b:longint):longint;
begin
   if a>b then exit(b) else exit(a);
end;
    
begin
   readln(n,m);
    for i:=1 to n do
    begin
        read(x);
        a[i]:=ord(x)-64;
    end;
    fillchar(f,sizeof(f),$7f);
    for i:=1 to m do f[0,i]:=0;
    f[1,a[1]]:=0;
    for i:=1 to n do
    begin
          for j1:=1 to m do   //i-1
          begin
              if j1<>a[i] then f[i,a[i]]:=min(f[i,a[i]],f[i-1,j1]);
              for j:=1 to m do if j<>a[i] then //change
              if j<>j1 then f[i,j]:=min(f[i,j],f[i-1,j1]+1)
          end;
    end;
    ans:=maxlongint;
    for i:=1 to m do ans:=min(ans,f[n,i]);
    writeln(ans);
    readln;readln;
end.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值