[noip2015]斗地主(dfs+贪心)

来源:互联网 发布:java udp服务器 编辑:程序博客网 时间:2024/06/05 11:52

题目:

我是超链接

题解:

一开始就照着大暴力的方向去写,然后华丽丽的T了,只有45pts
然后幡然醒悟:这不是一个普通的暴力!这是一个贪心!
先不考虑顺子的情况,贪心算出连带和单出的情况,按照出的牌从多到少来贪心

代码:

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int to[20]={0, 13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};//大小序 int m,n,p[20],c[20],ans;int calc() {    int res=0;    memset(c,0,sizeof(c));    for (int i = 0; i <= 13; ++i) ++c[p[i]];    while (c[4]>0 && c[2]>1) c[4]-=1,c[2]-=2,++res;    while (c[4]>0 && c[1]>1) c[4]-=1,c[1]-=2,++res;    while (c[4]>2) c[4]-=2,++res;    while (c[4]>0 && c[2]>0) c[4]-=1,c[2]-=1,++res;    while (c[3]>0 && c[2]>0) c[3]-=1,c[2]-=1,++res;    while (c[3]>0 && c[1]>0) c[3]-=1,c[1]-=1,++res;    return res + c[1] + c[2] + c[3] + c[4];}void ss(int s){    int pos,tot;    if (s>=ans) return;    ans=min(ans,s+calc());//不带顺子贪心考虑    for (int i=2;i<=13;i++)//3-A       for (int j=1;j<=3;j++)//1-3顺         if (p[i]>=j)//能成为开始         {            tot=0;            for (pos=i;p[pos]>=j;pos++) p[pos]-=j,tot+=j;             for (;--pos>=i;p[pos]+=j,tot-=j)//可以发现不管是什么顺子,至少是5张牌               if (tot>=5) ss(s+1);        }}int main() {    int T,n;    scanf("%d%d",&T,&n);    while (T--)     {        int x,y;        memset(p,0,sizeof(p));        for (int i=1;i<=n;i++)          scanf("%d%d",&x,&y),++p[to[x]];        ans=100;ss(0);        printf("%d\n", ans);    }}