bzoj 4325: NOIP2015 斗地主 dfs

来源:互联网 发布:恢复软件 编辑:程序博客网 时间:2024/05/29 20:01

题目

传送门

分析

毫无花哨的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.
0 0
原创粉丝点击