您的位置:首页 > 其它

bzoj 4325: NOIP2015 斗地主 dfs

2016-10-24 19:36 477 查看

题目

传送门

分析

毫无花哨的dfs,分n多种情况考虑,貌似加了最优化剪枝。

这是在比赛场上码的程序,很开心啊当场就AC了,用的是pascal,不怎么优美不过也就这个样了。

据说正解是dp还有dancing link之类的神奇的东东,表示不太懂。

貌似在ccf上测出来只有95分,不过也够我吹一年了。

不懂得就自己看程序吧。

var
t,n,ans,i,l,x,y:longint;
a:array[0..13] of longint;

function min(x,y:longint):longint;
begin
if x<y
then exit(x)
else exit(y);
end;

procedure dfs(x,y:longint);
var
i,j,k,l,s:longint;
begin
if x=0 then
begin
if y<ans then ans:=y;
exit;
end;
if y>=ans then exit;
for i:=1 to 13 do
if a[i]>2 then
begin
a[i]:=a[i]-3;
for j:=0 to 13 do
if (i<>j)and(a[j]>0) then
begin
dec(a[j]);
dfs(x-4,y+1);
inc(a[j]);
if a[j]>1 then
begin
a[j]:=a[j]-2;
dfs(x-5,y+1);
a[j]:=a[j]+2;
end;
end;
a[i]:=a[i]+3;
end;

for i:=3 to 10 do
begin
s:=maxlongint;
for j:=i to i+3 do
s:=min(s,a[j]);
for j:=i+4 to 13 do
begin
s:=min(s,a[j]);
for k:=1 to min(s,1) do
begin
for l:=i to j do
a[l]:=a[l]-k;
dfs(x-k*(j-i+1),y+1);
for l:=i to j do
a[l]:=a[l]+k;
end;
end;
s:=min(s,a[1]);
for j:=1 to min(s,1) do
begin
for k:=i to 13 do
a[k]:=a[k]-j;
a[1]:=a[1]-j;
dfs(x-j*(13-i+2),y+1);
for k:=i to 13 do
a[k]:=a[k]+j;
a[1]:=a[1]+j;
end;
end;

for i:=3 to 12 do
begin
s:=maxlongint;
for j:=i to i+1 do
s:=min(s,a[j]);
for j:=i+2 to 13 do
begin
s:=min(s,a[j]);
if s<2 then break;
for k:=2 to min(s,2) do
begin
for l:=i to j do
a[l]:=a[l]-k;
dfs(x-k*(j-i+1),y+1);
for l:=i to j do
a[l]:=a[l]+k;
end;
end;
s:=min(s,a[1]);
for j:=2 to min(s,2) do
begin
for k:=i to 13 do
a[k]:=a[k]-j;
a[1]:=a[1]-j;
dfs(x-j*(13-i+2),y+1);
for k:=i to 13 do
a[k]:=a[k]+j;
a[1]:=a[1]+j;
end;
end;

for i:=3 to 13 do
begin
s:=maxlongint;
s:=min(s,a[i]);
for j:=i+1 to 13 do
begin
s:=min(s,a[j]);
if s<3 then break;
k:=3;
for l:=i to j do
a[l]:=a[l]-k;
dfs(x-k*(j-i+1),y+1);
for l:=i to j do
a[l]:=a[l]+k;
end;
s:=min(s,a[1]);
for j:=3 to min(s,3) do
begin
for k:=i to 13 do
a[k]:=a[k]-j;
a[1]:=a[1]-j;
dfs(x-j*(13-i+2),y+1);
for k:=i to 13 do
a[k]:=a[k]+j;
a[1]:=a[1]+j;
end;
end;

for i:=1 to 13 do
if a[i]=4 then
begin
a[i]:=a[i]-4;
for j:=0 to 12 do
for k:=j+1 to 13 do
if (i<>j)and(j<>k)and(i<>k) then
for l:=1 to min(min(a[j],a[k]),2) do
begin
a[j]:=a[j]-l;
a[k]:=a[k]-l;
dfs(x-l*2-4,y+1);
a[j]:=a[j]+l;
a[k]:=a[k]+l;
end;
for j:=0 to 13 do
if i<>j then
for k:=1 to a[j] div 2 do
begin
a[j]:=a[j]-k*2;
dfs(x-k*2-4,y+1);
a[j]:=a[j]+k*2;
end;
a[i]:=a[i]+4;
end;
for i:=0 to 13 do
if a[i]>0 then inc(y);
if y<ans then ans:=y;
end;

begin
readln(t,n);
for l:=1 to t do
begin
fillchar(a,sizeof(a),0);
for i:=1 to n do
begin
readln(x,y);
inc(a[x]);
end;
ans:=maxlongint;
dfs(n,0);
writeln(ans);
end;
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: