• [NOIP2015] 斗地主(搜索)


    题目描述

    牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、方片的A到K加上大小王的共54张牌来进行的扑克牌游戏。在斗地主中,牌的大小关系根据牌的数码表示如下:3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王,而花色并不对牌的大小产生影响。每一局游戏中,一副手牌由n张牌组成。游戏者每次可以根据规定的牌型进行出牌,首先打光自己的手牌一方取得游戏的胜利。

    现在,牛牛只想知道,对于自己的若干组手牌,分别最少需要多少次出牌可以将它们打光。请你帮他解决这个问题。

    需要注意的是,本题中游戏者每次可以出手的牌型与一般的斗地主相似而略有不同。

    具体规则如下:

    输入输出格式

    输入格式:

    第一行包含用空格隔开的2个正整数Tn,表示手牌的组数以及每组手牌的张数。

    接下来T组数据,每组数据n行,每行一个非负整数对aibi表示一张牌,其中ai示牌的数码,bi表示牌的花色,中间用空格隔开。特别的,我们用1来表示数码A,11表示数码J,12表示数码Q,13表示数码K;黑桃、红心、梅花、方片分别用1-4来表示;小王的表示方法为01,大王的表示方法为02。

    输出格式:

    共T行,每行一个整数,表示打光第i手牌的最少次数。

    输入输出样例

    输入样例#1:
    1 8
    7 4
    8 4
    9 1
    10 4
    11 1
    5 1
    1 4
    1 1
    输出样例#1:
    3
    
    输入样例#2:
    1 17
    12 3
    4 3
    2 3
    5 4
    10 2
    3 3
    12 2
    0 1
    1 3
    10 1
    6 2
    12 1
    11 3
    5 2
    12 4
    2 2
    7 2
    
    输出样例#2:
    6
    

    说明

    样例1说明

    共有1组手牌,包含8张牌:方片7,方片8,黑桃9,方片10,黑桃J,黑桃5,方片A以及黑桃A。可以通过打单顺子(方片7,方片8,黑桃9,方片10,黑桃J),单张牌(黑桃5)以及对子牌(黑桃A以及方片A)在3次内打光。

    对于不同的测试点, 我们约定手牌组数T与张数n的规模如下:

    数据保证:所有的手牌都是随机生成的。

    • 看道题目我只能说出题人真会玩,斗地主都出来了。
    • 这个斗地主的规则与一般的不太一样(虽然是从百度百科上粘的)。
    • 看到随机数据我就松了一口气,因为这样的话不会有出题人给的神坑!!!
    • 仔细分析,其实这道题没有什么完美的算法,基本确定思路:爆搜(深度优先搜索)。
    • 本题花色没什么卵用,只是用来区分大小王。
    • 再分析:出牌顺序不会影响出牌次数。
    • 按照常规的思路,肯定要先打顺子。
    • 所以就先搜顺子;注意:连着的几张牌不一定当做一个顺子一起打出,比如说6 7 8 8 9 9 10 10 J Q这组牌,如果先打出678910JQ,再打3个单牌,就不如打两个顺子678910 8910JQ更优。
    • 然后出带牌,也要按照一定的顺序,比如:四带两对,四带两单,三带。
    • 然后把所有不能连着出的牌统计一下,加到当前的答案中,并更新答案。
    • 注意本题搜索技巧:每次进入下一步是统计一下当前牌号的种类数(因为同一号的牌一定能一下打出),并更新答案;因为A能连成顺子而2不能,所以在将牌编号时可以将3-K编号为1-11,A编号为12,2编号为13,小王为14,大王为15,这样搜的时候就会比较方便;如果有双王先打出双王,因为这样对牌局没有影响(双王不能被同时带出,但单个王可以被带出);注意利用前缀和的思想,这样可以使搜索更方便(尤其是搜顺子的时候)。
    • 然后就是考验代码能力的时候了,本人蒟蒻,调了半天才调出来,代码很丑。
    • 复杂度玄学,不过对于随机数据来说不成问题,期望通过本题,最慢的点300+ms。
      1 var
      2     t,n,i,j,x,y,anss,tt,now,ans        :longint;
      3     sum                             :Array[0..15] of longint;
      4     f1,f2,f3,s1,s2,s3                :array[0..14] of longint;
      5     ff                                :boolean;
      6 
      7 function min(x,y:longint):longint;
      8 begin
      9     if x<y then exit(x) else exit(y);
     10 end;
     11 
     12 function find():longint;
     13 var
     14     i,summ                             :longint;
     15 begin
     16     summ:=0;
     17     for i:=1 to 15 do if (sum[i]>0) then inc(summ);
     18     exit(summ);
     19 end;
     20 
     21 procedure dfs(x:longint);
     22 var
     23     i,j,k                             :longint;
     24     l,r,max,t,q,o                    :longint;
     25 begin
     26     q:=find();
     27     if q+x-1<anss then anss:=q+x-1;//tongji
     28     {---------------------------------------------------}
     29     fillchar(f1,sizeof(f1),0);
     30     fillchar(s1,sizeof(s1),0);
     31     for i:=1 to 12 do if (sum[i]>=3) then f1[i]:=1;
     32     for i:=1 to 12 do s1[i]:=s1[i-1]+f1[i];
     33     max:=0;
     34     for i:=1 to 12 do
     35     for j:=i+1 to 12 do
     36         if j<=l then continue;
     37         if (s1[j]-s1[i-1]=j-i+1) then
     38         begin
     39             if (j-i+1>max) then
     40             begin
     41                 max:=j-i+1;
     42                 l:=i;
     43                 r:=j;
     44             end;
     45         end;
     46     if max>=2 then
     47     begin
     48         for i:=l to r do
     49         for j:=r downto l do
     50         begin
     51             if j-i+1<2 then continue;
     52             for k:=i to j do dec(sum[k],3);
     53             dfs(x+1);
     54             for k:=i to j do inc(sum[k],3);
     55         end;
     56     end;//san shun zi
     57     {----------------------------------------------------------}
     58     fillchar(f2,sizeof(f2),0);
     59     fillchar(s2,sizeof(s2),0);
     60     for i:=1 to 12 do if (sum[i]>=2) then f2[i]:=1;
     61     for i:=1 to 12 do s2[i]:=s2[i-1]+f2[i];
     62     max:=0;
     63     for i:=1 to 12 do
     64     for j:=i+1 to 12 do
     65         if (s2[j]-s2[i-1]=j-i+1) then
     66         begin
     67             if (j-i+1>max) then
     68             begin
     69                 max:=j-i+1;
     70                 l:=i;
     71                 r:=j;
     72             end;
     73         end;
     74     if max>=3 then
     75     begin
     76         for i:=l to r do
     77         for j:=r downto l do
     78         begin
     79             if j-i+1<3 then continue;
     80             for k:=i to j do dec(sum[k],2);
     81             dfs(x+1);
     82             for k:=i to j do inc(sum[k],2);
     83         end;
     84     end;//shuang shun zi
     85     {--------------------------------------------------------}
     86     fillchar(f3,sizeof(f3),0);
     87     fillchar(s3,sizeof(s3),0);
     88     for i:=1 to 12 do if (sum[i]<>0) then f3[i]:=1;
     89     for i:=1 to 12 do s3[i]:=s3[i-1]+f3[i];
     90     max:=0;
     91     for i:=1 to 12 do
     92     for j:=i+1 to 12 do
     93         if (s3[j]-s3[i-1]=j-i+1) then
     94         begin
     95             if (j-i+1>max) then
     96             begin
     97                 max:=j-i+1;
     98                 l:=i;
     99                 r:=j;
    100             end;
    101         end;
    102     if max>=5 then
    103     begin
    104         for i:=l to r do
    105         for j:=r downto l do
    106         begin
    107             if j-i+1<5 then continue;
    108             for k:=i to j do dec(sum[k]);
    109             dfs(x+1);
    110             for k:=i to j do inc(sum[k]);
    111         end;
    112     end;//dan shun zi
    113     {--------------------------------------------------------}
    114     for i:=1 to 13 do
    115     begin
    116         if (sum[i]=4) then
    117         begin
    118             dec(sum[i],4);
    119             for j:=1 to 15 do
    120             begin
    121                 if sum[j]<2 then continue;
    122                 for k:=j+1 to 13 do
    123                 begin
    124                     if sum[k]<2 then continue;
    125                     dec(sum[j],2);
    126                     dec(sum[k],2);
    127                     dfs(x+1);
    128                     inc(sum[j],2);
    129                     inc(sum[k],2);
    130                 end;
    131             end;
    132             inc(sum[i],4);
    133         end;
    134     end; //4 dai 2
    135     {-------------------------------------------------------}
    136     for i:=1 to 13 do
    137     begin
    138         if (sum[i]=4) then
    139         begin
    140             dec(sum[i],4);
    141             for j:=1 to 13 do
    142             begin
    143                 if sum[j]<>1 then continue;
    144                 for k:=j+1 to 15 do
    145                 begin
    146                     if sum[k]<>1 then continue;
    147                     dec(sum[j]);
    148                     dec(sum[k]);
    149                     dfs(x+1);
    150                     inc(sum[j]);
    151                     inc(sum[k]);
    152                 end;
    153             end;
    154             inc(sum[i],4);
    155         end;
    156     end; //4 dai 1
    157     {---------------------------------------------------------}
    158     for i:=1 to 13 do
    159     begin
    160         if (sum[i]=3) then
    161         begin
    162             dec(sum[i],3);
    163             for j:=1 to 15 do
    164             begin
    165                 if (sum[j]>2) or (sum[j]<1) then continue;
    166                 t:=sum[j];
    167                 sum[j]:=0;
    168                 dfs(x+1);
    169                 sum[j]:=t;
    170             end;
    171             inc(sum[i],3);
    172         end;
    173     end;//san dai 1/2
    174 end;
    175 
    176 begin
    177     read(t,n);
    178     while (t>0) do
    179     begin
    180         dec(t);
    181         fillchar(sum,sizeof(sum),0);
    182         for i:=1 to n do
    183         begin
    184             read(x,y);
    185             if (x>=3) then inc(sum[x-2]) else
    186             if (x=1) then inc(sum[12]) else
    187             if (x=2) then inc(sum[13]) else
    188             if (x=0) and (y=1) then inc(sum[14]) else
    189             if (x=0) and (y=2) then inc(sum[15]); 
    190         end;
    191         ans:=0;
    192         if (sum[14]>0) and (sum[15]>0) then
    193         begin
    194             tt:=min(sum[14],sum[15]);
    195             dec(sum[14],tt);
    196             dec(sum[15],tt);
    197             inc(ans,tt);
    198         end;//double jokers
    199         anss:=maxlongint;
    200         dfs(ans+1);
    201         writeln(anss);
    202         continue;
    203     end;
    204 end.
  • 相关阅读:
    Reverse Integer
    Same Tree
    BST(Binary Search Tree)
    Maximum Depth of Binary Tree
    Single Number
    Computer System Basic Concept(2)
    破解企业QQ对个人QQ登陆的限制(原创)
    鸟哥的Linux私房菜.基础学习篇(摘要)(持续更新)
    Linux系列书籍
    【总结】关于彩虹表学习阶段性总结
  • 原文地址:https://www.cnblogs.com/zoewilly/p/6039242.html
Copyright © 2020-2023  润新知