题目
分析
仔细看,这道题着实想不到什么优美的算法,那么基本确定方向——dfs。
先分析,这题的花色是没用的
我们再分析,会发现这题的出牌顺序是不影响答案的
那么我们便可以先出牌多的(因为这样答案便会先便小,那么便可以方便后面的剪枝)
也就是我们先打顺子再打带牌!
顺子是没有什么技巧的,便直接暴搜(当然也是先暴搜长度长的)
带牌是有技巧的!
我们发现带牌是不与牌本身的点数有关的,
于是我们便可以分别统计有多少种牌是四张的,三张的,两张的,一张的。
最后注意三点:
1.我们可以拆开牌来打
也就是若我想打四带两张单张牌
我们便可以拆三张的拆成两张的和一张的。
或者两张一张的,或者一张两张的。
2.王是不能带出去的,也就是对王是单独出的。
3.2,王是不能顺子的
这样便可以放心的暴搜了。
var
n,t,x,y,i,ans:longint;
a:array[0..15] of longint;
p:array[0..4] of longint;
toe:array[1..3] of longint=(5,3,2);
procedure dfs(an:longint);
var i,j:longint;
begin
if an>=ans then exit;j:=0;
for i:=1 to 4 do j:=j+p[i];
if j+an<ans then ans:=j+an;
if p[4]>0 then begin
dec(p[4]);
for i:=4 downto 2 do if p[i]>0 then begin
dec(p[i]);inc(p[i-2]);
for j:=2 to 4 do
if p[j]>0 then begin
dec(p[j]);inc(p[j-2]);
dfs(an+1);
inc(p[j]);dec(p[j-2]);
end;
inc(p[i]);dec(p[i-2]);
end;
for i:=1 to 4 do if p[i]>0 then begin
dec(p[i]);inc(p[i-1]);
for j:=1 to 4 do
if p[j]>0 then begin
dec(p[j]);inc(p[j-1]);
dfs(an+1);
inc(p[j]);dec(p[j-1]);
end;
inc(p[i]);dec(p[i-1]);
end;
i:=i;
inc(p[4]);
end;
if p[3]>0 then begin
dec(p[3]);
for i:=2 to 4 do if p[i]>0 then begin
dec(p[i]);inc(p[i-2]);dfs(an+1);inc(p[i]);dec(p[i-2]);
end;
for i:=1 to 4 do if p[i]>0 then begin
dec(p[i]);inc(p[i-1]);dfs(an+1);inc(p[i]);dec(p[i-1]);
end;
inc(p[3]);
end;
end;
procedure solve(an:longint);
var i,j,k,jj:longint;
begin
if an>=ans then exit;
fillchar(p,sizeof(p),0);
for i:=1 to 15 do inc(p[a[i]]);
if p[0]=15 then begin
ans:=an;exit;
end;
dfs(an);
for k:=1 to 3 do begin
for i:=1 to 14-toe[k]-1 do
if a[i]>=k then begin
for j:=i+1 to 12 do
if a[j]<k then break;
if a[j]<k then dec(j);
if j-i+1<toe[k] then continue;jj:=j;
for j:=i to i+toe[k]-1 do dec(a[j],k);
solve(an+1);
for j:=i+toe[k] to jj do begin
dec(a[j],k);
solve(an+1);
end;
for j:=i to jj do inc(a[j],k);
end;
i:=i;
end;
end;
begin
readln(t,n);
for t:=1 to t do begin
ans:=13;
fillchar(a,sizeof(a),0);
for i:=1 to n do begin
readln(x,y);
if (x>=3)and(x<=13) then inc(a[x-2])
else if x=1 then inc(a[12])
else if x=2 then inc(a[13])
else if y=1 then inc(a[14]) else inc(a[15]);
end;
if (a[14]>0)and(a[15]>0) then begin
a[14]:=0;a[15]:=0;
solve(1);
a[14]:=1;a[15]:=1;
end;
solve(0);
writeln(ans);
end;
close(input);close(output);
end.