• NOIP2015提高组D1T3 斗地主


    问一副排n张,n<=23最少打几次打完,数据组数T<=100。

    面向数据编程。。

    前30分:乱暴力?没有顺子,把单、对子、炸弹、三张、王炸、三带一判一次即可。

    前70分:状压,先预处理哪些状态能一次出完,用这些状态来转移,2^n*n*T。实际得分可能比期望的高一些??

    满分:如果不打顺子,最优策略是可以确定的,三和四的能带走一二的就带走。所以dfs打顺子,然后贪心出剩下的牌。可以把ans做全局变量,然后搜索时>ans就退出以剪枝。

      1 #include<cstring>
      2 #include<cstdlib>
      3 #include<cstdio>
      4 //#include<assert.h>
      5 //#include<time.h>
      6 #include<math.h>
      7 //#include<queue>
      8 #include<algorithm>
      9 #include<iostream>
     10 using namespace std;
     11 
     12 bool isdigit(char c) {return c>='0' && c<='9';}
     13 int qread()
     14 {
     15     char c;int s=0,f=1;while (!isdigit(c=getchar())) f=(c=='-'?-1:1);
     16     do s=s*10+c-'0'; while (isdigit(c=getchar())); return s*f;
     17 }
     18 
     19 int T,n,ans;
     20 int a[25],cnt[25];
     21 int calc()
     22 {
     23     int ans=0;
     24     memset(cnt,0,sizeof(cnt));
     25     for (int i=1;i<=13;i++) cnt[a[i]]++;
     26     for (int i=1;i<=4;i++) cout<<cnt[i]<<' ';cout<<endl;
     27     bool wang=0;
     28     if (a[14] && a[15]) cnt[2]++,wang=1;
     29     else if (a[14] || a[15]) cnt[1]++;else{}
     30     
     31     while (cnt[4] && cnt[1]>1) ans++,cnt[4]--,cnt[1]-=2;
     32     while (cnt[4] && cnt[2]>1) ans++,cnt[4]--,cnt[2]-=2;
     33     while (cnt[3] && cnt[1]) ans++,cnt[3]--,cnt[1]--;
     34     while (cnt[3] && cnt[2])
     35     {
     36         if (cnt[2]==1 && wang) break;
     37         ans++,cnt[3]--,cnt[2]--;
     38     }
     39     ans+=cnt[1]+cnt[2]+cnt[3]+cnt[4];
     40     return ans;
     41 }
     42 void dfs(int dep)
     43 {
     44     if (dep>ans) return;
     45     int tmp=calc();
     46     if (dep+tmp<ans) ans=dep+tmp;
     47     //单顺子 
     48     for (int i=1;i<=8;i++)
     49     {
     50         int j=i;
     51         while (j<13 && a[j]) j++;
     52         for (int play=i+4;play<j;play++)
     53         {
     54             for (int k=i;k<=play;k++) a[k]--;
     55             dfs(dep+1);
     56             for (int k=i;k<=play;k++) a[k]++;
     57         }
     58     }
     59     //连对
     60     for (int i=1;i<=10;i++)
     61     {
     62         int j=i;
     63         while (j<13 && a[j]>1) j++;
     64         for (int play=i+2;play<j;play++)
     65         {
     66             for (int k=i;k<=play;k++) a[k]-=2;
     67             dfs(dep+1);
     68             for (int k=i;k<=play;k++) a[k]+=2;
     69         }
     70     }
     71     //三连对 
     72     for (int i=1;i<=11;i++)
     73     {
     74         int j=i;
     75         while (j<13 && a[j]>2) j++;
     76         for (int play=i+1;play<j;play++)
     77         {
     78             for (int k=i;k<=play;k++) a[k]-=3;
     79             dfs(dep+1);
     80             for (int k=i;k<=play;k++) a[k]+=3;
     81         }
     82     }
     83 }
     84 int main()
     85 {
     86     T=qread();
     87     n=qread();
     88     int x,y;
     89 while (T--)
     90 {
     91     memset(a,0,sizeof(a));
     92     for (int i=1;i<=n;i++)
     93     {
     94         x=qread();y=qread();
     95         if (x)
     96         {
     97             if (x>2) a[x-2]++;
     98             else a[x+11]++;
     99         }
    100         else a[13+y]++;
    101     }
    102     ans=n;dfs(0);
    103     printf("%d
    ",ans);
    104 }
    105     return 0;
    106 }
    View Code

    错误!有诸多未考虑到的情况,比如,4张3,4张3,3张5,可以两次打完;4张3,3张4,3张5,2张6,也可以两次打完。。。

    不过这样可以满足网上大部分的数据了。。

  • 相关阅读:
    字符的编码
    数据的基本类型和内置方法(二)
    基本的数据类型和内置方法介绍 (一)
    流程运算 if while for
    用户交换 基本数据类型 基本运算符 格式化输出
    机器语言发展简介和变量的介绍
    计算机基础
    Python学习建议和要求总结
    CH135 最大子序和 题解报告
    HRBUST1356 Leyni,罗莉和队列 题解报告
  • 原文地址:https://www.cnblogs.com/Blue233333/p/7752922.html
Copyright © 2020-2023  润新知