P2668 斗地主 noip2015day1 T3(dfs)

https://www.luogu.org/problemnew/show/P2668

题解:

显然这题有很多没用的条件,

【1】将所有拍重新排序,3是1号,等等k是11号,A是12号,2是13号,王是1号;

【2】火箭==对子 ,炸弹变成四带二更优,三张牌变成三带二或三带一更优(不是顺子的牌用贪心的思想,最优解是一定的);

【3】对于顺子,用dfs暴力枚举每种情况;

附上最短ac代码:

#include<bits/stdc++.h>//王==14 2--13 A--12 k--11
using namespace std;
const int maxn = 25 ;
int T,n,ans,tmp[maxn];
void shunzi(int x,int y,int dx,int num){//暴力枚举顺子的个数 
    int i,j;
    for(i=1;i<=x;i++){
        for(j=i;j<=y;j++){
            tmp[j]-=dx;
            if(tmp[j]<0) break;
            void dfs(int num);
            if(j-i>=y-x) dfs(num+1);
        }
        if(j==13) j--;
        while(i<=j--) tmp[j+1]+=dx;
    }
}
void dfs(int num){
    if(num > ans) return;
    int a1(0),a2(0),a3(0),a4(0);//单牌,对牌,三牌,四牌; 
    for(int i=1;i<=14;i++)
        if(tmp[i]==1) a1++;//
        else if(tmp[i]==2) a2++;//
    for(int i=1;i<=14;i++)
        if(tmp[i]==3){
            a3++;
            if(a1>=1) a1--;//三代一 
            else if(a2>=1) a2--;//三代二 
        }
        else if(tmp[i]==4){
             a4++;
             if(a1>=2) a1-=2;//四带二 
             else if(a2>=2) a2-=2;//四带俩对 
                   else if(a2>=1) a2--;//四带对 
        }
    ans=min( ans , num+a1+a2+a3+a4 );
    shunzi(8,12,1,num);
    shunzi(10,12,2,num);
    shunzi(11,12,3,num);
}
int main(){
    cin>>T>>n;
    while(T--){
        ans=(1<<30);
        memset(tmp,0,sizeof(tmp));
        for(int i=1,a,b;i<=n;i++){
            scanf("%d%d",&a,&b);
            if(a>=3) tmp[a-2]++;
            if(a==0) tmp[14]++;
            if(a==2) tmp[13]++;
            if(a==1) tmp[12]++;
        }
        dfs(0);
        cout<<ans<<endl;
    }
    return 0;
}

 

posted @ 2019-06-02 23:47  寒方  阅读(149)  评论(0编辑  收藏  举报