算法:DP
分析:看了题解之后,发现这道题并不是那么难做,之前一直没有看出这道题究竟DP在哪,现在终于明白了。
用f[st,a,b,c]表示到st这个位置时,剩余A(a个),B(b个),C(c个),然后就进行DP,每次可以选择放A或放B或放C。总共有三种转移方式。
分析:看了题解之后,发现这道题并不是那么难做,之前一直没有看出这道题究竟DP在哪,现在终于明白了。
用f[st,a,b,c]表示到st这个位置时,剩余A(a个),B(b个),C(c个),然后就进行DP,每次可以选择放A或放B或放C。总共有三种转移方式。
其实这到题的DP不是特别的明显,还是比较像记忆化搜索。
program worker;
const
maxn=100;
var
n:longint;
a:array [0..maxn] of longint;
f:array [0..maxn,0..10,0..10,0..10] of longint;
b:array [0..maxn,0..10,0..10,0..10] of boolean;
procedure init;
var
i:longint;
t:char;
begin
fillchar(b,sizeof(b),false);
fillchar(f,sizeof(f),100);
readln(n);
for i:=1 to n do
begin
readln(t);
a[i]:=ord(t)-64;
end;
end;
function min(x,y:longint):longint;
begin
if x<y then exit(x) else exit(y);
end;
function dfs(st,a1,b1,c1:longint):longint;{st表示到哪个位置,有A a1个,有B b1个,有C c1个。}
var
i,rest:longint;
begin
rest:=10-a1-b1-c1;
for i:=1 to rest do{把还能装多少个装上。}
begin
inc(st);
if st<=n then
begin
if a[st]=1 then inc(a1);
if a[st]=2 then inc(b1);
if a[st]=3 then inc(c1);
end
else break;
end;
if st>=n then{如果大于等于N,那么直接算出用几次。}
begin
f[n,a1,b1,c1]:=ord(a1>0)+ord(b1>0)+ord(c1>0);
b[n,a1,b1,c1]:=true;
exit(f[n,a1,b1,c1]);
end;
if b[st,a1,b1,c1] then exit(f[st,a1,b1,c1]){如果已经算出就不用计算了。}
else{否则三种转移方式。}
begin
b[st,a1,b1,c1]:=true;
f[st,a1,b1,c1]:=min(f[st,a1,b1,c1],dfs(st,0,b1,c1)+1);
f[st,a1,b1,c1]:=min(f[st,a1,b1,c1],dfs(st,a1,0,c1)+1);
f[st,a1,b1,c1]:=min(f[st,a1,b1,c1],dfs(st,a1,b1,0)+1);
end;
exit(f[st,a1,b1,c1]);
end;
begin
init;
writeln(dfs(0,0,0,0));
end.