斗地主(NOIP2015)

原题传送门

神奇的题目。。

一开始我准备打暴力直接搜答案。

然后发现。。

无限TLE。。

因为O((logN)^14*T)BOOM。。

然后Zxyer告诉可以只DFS顺子。。。其他的可以一步搞出来。。

然后就0ms了!

Orz zxyer

下面贴代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define inf 0x7fffffff
using namespace std;
int pai[16];
int s[5];
int ans=inf,n,t,x;
int cal(){
    s[1]=s[2]=s[3]=s[4]=0;
    int ans1=0;
    for (register int i=1;i<=15;i++)s[pai[i]]++;
    if(pai[14]&&pai[15])ans1++,s[1]-=2;
    while(s[4]&&s[1]>1)ans1++,s[4]--,s[1]-=2;
    while(s[4]&&s[2]>1)ans1++,s[4]--,s[2]-=2;
    while(s[3]&&s[2])ans1++,s[3]--,s[2]--;
    while(s[3]&&s[1])ans1++,s[3]--,s[1]--;
    return ans1+s[4]+s[3]+s[2]+s[1];
}
void dfs(int q){
    if(q>=ans)return;
    ans=min(ans,q+cal());
    register int j;
    for(register int i=1;i<=11;i++)
    {
        j=i;
        while((j<13)&&(pai[j]>=3)){pai[j++]-=3;
        if(j-i>1)dfs(q+1);} 
        while(j-i)pai[--j]+=3;
    }
    for(register int i=1;i<=10;i++)
    {
        j=i;
        while((j<13)&&(pai[j]>=2)){pai[j++]-=2;
        if(j-i>2)dfs(q+1);
        } 
        while(j-i)pai[--j]+=2;
    }
    for(register int i=1;i<=8;i++)
    {
        j=i;
        while((j<13)&&(pai[j])){--pai[j++];
        if(j-i>4)dfs(q+1);} 
        while(j-i)++pai[--j];
    }
}
int getnum(int q){
    int y;
    scanf("%d",&y);
    if(!x)return y+13;
    if(x<3)return x+11;
    return x-2;
}
int main(){
    scanf("%d",&t);scanf("%d",&n);
    for(int i=1;i<=t;i++)
    {
        memset(pai,0,sizeof(pai));
        ans=inf;
        for(int i=1;i<=n;i++)
        {
        scanf("%d",&x);
        pai[getnum(x)]++;
        }
        dfs(0);
        printf("%d\n",ans);
    }
    return 0; 
}

 

posted @ 2017-05-18 11:41  ghostfly233  阅读(230)  评论(0编辑  收藏  举报