P2422 [LOJ] [NOIP2015] 斗地主
\(\texttt{LOJ}\) 题面:
考场想 \(\texttt{Dfs}\) 直接跑过去,打炸了。
其实可以发现 \(\text{四带二}\)、 \(\text{三带二}\)、 \(\text{三带一}\)、 \(\text{炸弹}\)、 \(\text{火箭}\)、 \(\text{三牌}\)、 \(\text{对子}\)、 \(\text{单牌}\) 这些最优组合是固定的。且根据贪心思想,我们必须先打多的牌。
好比我们现在打的是 \(\text{四带二}\),我们可以把这个\(\text{四}\) 分成 \(\text{二} \times 2\),然后用 \(\text{三带二} \times 3\) 打出去。虽然个数不变,但是浪费了别人三个 \(\text{三带 N}\) 的机会。
顺子显然会直接影响散牌的状态,这时候就用搜索即可。
Uses math;
Const
total=20;
var
num,get:array[-1..total] of longint;
i,x,y,n,m,ans:longint;
function Disperse:longint;
var i,k:longint;
begin
Disperse:=0; for i:=0 to 4 do get[i]:=0;
for i:=0 to 13 do inc(get[num[i]]);
while (get[4]>0)and(get[2]>=2) do begin dec(get[4]); dec(get[2],2); inc(Disperse); end;
while (get[4]>0)and(get[1]>=2) do begin dec(get[4]); dec(get[1],2); inc(Disperse); end;
while (get[4]>0)and(get[2]>0) do begin dec(get[4]); dec(get[2]); inc(Disperse); end;
while (get[3]>0)and(get[2]>0) do begin dec(get[3]); dec(get[2]); inc(Disperse); end;
while (get[3]>0)and(get[1]>0) do begin dec(get[3]); dec(get[1]); inc(Disperse); end;
inc(Disperse,get[1]+get[2]+get[3]+get[4]);
end;
procedure Dfs(way:longint);
var
p,i,j,k,x:longint;
begin
if way>ans then exit; ans:=min(ans,way+Disperse);
for p:=3 downto 1 do // 三个顺子
for i:=2 to 13 do
begin
x:=i;
while (num[x]>=p)and(x<=13) do
begin
inc(x);
if ((p=1)and(x-i>=5))or((p=2)and(x-i>=3))or((p=3)and(x-i>=2)) then
begin
for j:=i to x-1 do dec(num[j],p); Dfs(way+1);
for j:=i to x-1 do inc(num[j],p);
end;
end;
end;
end;
begin
read(m,n);
while m>0 do
begin
fillchar(num,sizeof(num),0); ans:=maxlongint;
for i:=1 to n do
begin
read(x,y);
if (x<>1)and(x<>0) then inc(num[x-1]);
if (x=1) then inc(num[13]);
if (x=0) then inc(num[0]);
end;
Dfs(0); writeln(ans); dec(m);
end;
end.
完结撒花!✿✿ヽ(゚▽゚)ノ✿