NOIP2015斗地主

乍一看,一脸茫然,没有前途

仔细一看,花色没用,有点前途?

在没有顺子的情况下还是可以乱搞不至于爆0

那么怎么乱搞呢?

核心当然是一次能多出就多出

能出4带两对就出4带两对,然后能出4带2就出4带2;

如果在出完所有的”4带“后对和单还有剩余我们就来出“3带”

同理,先出3带2再出3带1

如果还剩单和对那必是要单出的,所以直接加进步数就可以了

注意:无论是几带2都不可以带出去两个鬼,所以我们把鬼处理到单里面,

但是2个鬼是可以一起出的所以如果我们在最后剩的单大于等于2张而我们又恰好有两张鬼那么我们就可以在我们所得的次数-1=w=

然后我们可以发现(其实是题解君发现=。=)

在没有顺子或者顺子确定的情况下,我们的出牌次数是一定的

那么我们只需要dfs枚举顺子然后在该情况下用上述乱搞就可以了

对于我们找到的顺子,我们可以全出(可能需要拆牌)也可以选择出部分满足条件的顺子,多方案取优

注意对顺子的判定(QAQ卡好久)

注意多组数据的初始化(QAQ卡好久)

<span style="font-size:18px;">const
    l:array[1..3] of longint=(5,3,3);
var
    tt,n,x,ans          :longint;
    i                   :longint;
    a                   :array[0..25] of longint;
    num                 :array[0..15] of longint;
    cnt                 :array[0..5] of longint;//几个单、几个对、几个三个、几个四个
function min(a,b:longint):longint;
begin
   if a<b then exit(a) else exit(b);
end;

function play:longint;
var
    tt,t:longint;
    i:longint;
begin
   fillchar(cnt,sizeof(cnt),0);
   for i:=0 to 14 do inc(cnt[num[i]]);
   if (num[0]=2) then
   begin
      dec(cnt[2]);inc(cnt[1],2);
   end;
   t:=cnt[3]+cnt[4];
   //4 with
   tt:=min(cnt[4],cnt[2] >>1);
   dec(cnt[4],tt);dec(cnt[2],tt <<1);
   tt:=min(cnt[4],cnt[1] >> 1);
   dec(cnt[4],tt);dec(cnt[1],tt <<1);

   if (cnt[1]<>0) or (cnt[2]<>0) then
   begin
   //3 with
   tt:=min(cnt[3],cnt[2]);
   dec(cnt[3],tt);dec(cnt[2],tt);
   tt:=min(cnt[3],cnt[1]);
   dec(cnt[3],tt);dec(cnt[1],tt);
   end;
   //1 2 
   inc(t,cnt[1]+cnt[2]);
   if (cnt[1]>=2) and (num[0]=2) then dec(t); //double joker
   exit(t);
end;

procedure find(w,len:longint);
var
    i,j:longint;
    head:longint;
begin
   if (len<1) then exit;
   ans:=min(ans,w+play);
   find(w,len-1);

   head:=-1;
   for i:=3 to 14 do
    if (num[i]>=len) then
    begin
       if (head=-1) then head:=i
       else if (i>=head+l[len]-1) then
       begin
          for j:=head to i do dec(num[j],len);
          for j:=head to i do
          begin
             if (i>=j+l[len]-1) then find(w+1,len);
             inc(num[j],len);
          end;
       end;
    end else head:=-1;
end;

begin
   read(tt,n);
   while (tt>0) do
   begin
      dec(tt);
      fillchar(a,sizeof(a),0);
      fillchar(num,sizeof(num),0);
      ans:=maxlongint;
      for i:=1 to n do
      begin
         read(a[i],x);
         if (a[i]=1) then a[i]:=14;
         inc(num[a[i]]);
      end;
      //
      find(0,3);
      writeln(ans);
   end;
end.
</span>


                              ——by Eirlys
转载请注明出处=w=


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值