zoukankan      html  css  js  c++  java
  • 洛谷 P2668 & P2540 [ noip 2015 ] 斗地主 —— 搜索+贪心

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

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

    首先,如果没有顺子,那么有贪心最优解;

    所以先搜索顺子,再贪心求剩余的出牌方案;

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int T,n,a[15],t[15],ans,inf=0x3f3f3f3f;
    int calc()
    {
        int ret=0;
        memset(t,0,sizeof t);
        for(int i=0;i<=13;i++)t[a[i]]++;
        while(t[4]&&t[2]>=2)t[4]--,t[2]-=2,ret++;
        while(t[4]&&t[1]>=2)t[4]--,t[1]-=2,ret++;
        while(t[4]&&t[2])t[4]--,t[2]--,ret++;
        while(t[3]&&t[2])t[3]--,t[2]--,ret++;
        while(t[3]&&t[1])t[3]--,t[1]--,ret++;
        return ret+t[1]+t[2]+t[3]+t[4];
    }
    void dfs(int u)//顺子 
    {
        if(u>ans)return;
        int tmp=calc();
        if(u+tmp<ans)ans=u+tmp;
        for(int i=2,j;i<=13;i++)
        {
            for(j=i;j<=13;j++)if(a[j]<3)break;
            j--;
            if(j-i+1<2)continue;
            for(int k=j;k>=i+1;k--)
            {
                for(int l=i;l<=k;l++)a[l]-=3;
                dfs(u+1);
                for(int l=i;l<=k;l++)a[l]+=3;
            }
        }
        for(int i=2,j;i<=13;i++)
        {
            for(j=i;j<=13;j++)if(a[j]<2)break;
            j--;
            if(j-i+1<3)continue;
            for(int k=j;k>=i+2;k--)
            {
                for(int l=i;l<=k;l++)a[l]-=2;
                dfs(u+1);
                for(int l=i;l<=k;l++)a[l]+=2;
            }
        }
        for(int i=2,j;i<=13;i++)
        {
            for(j=i;j<=13;j++)if(!a[j])break;
            j--;
            if(j-i+1<5)continue;
            for(int k=j;k>=i+4;k--)
            {
                for(int l=i;l<=k;l++)a[l]--;
                dfs(u+1);
                for(int l=i;l<=k;l++)a[l]++;
            }
        }
    }
    int main()
    {
        scanf("%d%d",&T,&n);
        while(T--)
        {
            memset(a,0,sizeof a);
            for(int i=1,x,y;i<=n;i++)
            {
                scanf("%d%d",&x,&y);
                if(x==1)x=13;
                else if(x)x--;
                a[x]++;
            }
            ans=inf; dfs(0);
            printf("%d
    ",ans);
        }
        return 0;
    }

    增强版要考虑拆牌,看了题解,感觉好混乱...

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int T,n,a[15],t[15],ans,inf=0x3f3f3f3f;
    int calc()
    {
        int ret=0;bool wz=0;
        memset(t,0,sizeof t);
        if(a[0]==2)wz=1; t[1]+=a[0];
        for(int i=1;i<=13;i++)t[a[i]]++;
        while(!t[3]&&t[4]>1&&t[1]==1&&t[2]==1)t[4]-=2,t[1]--,t[2]--,ret+=2;//4=3+1,出四带二单和三带二
        while(!t[2]&&t[3]>1&&t[1]==1&&t[4]==1)t[3]-=2,t[1]--,t[4]--,ret+=2;//3=2+1,出四带二单和三带二
        if(t[3]+t[4]>t[1]+t[2])
            while(t[4]&&t[2]&&t[3])t[4]--,t[2]--,t[3]--,t[1]++,ret++;//3=2+1,出四带二对,余一单 
        if(t[3]+t[4]>t[1]+t[2])
            while(t[4]&&t[1]&&t[3])t[4]--,t[1]--,t[3]--,t[2]++,ret++;//3=2+1,出四带二单,余一对 
        while(t[4]&&t[2]>1)t[4]--,t[2]-=2,ret++;
        while(t[4]&&t[1]>1)t[4]--,t[1]-=2,ret++;
        while(t[4]&&t[2])t[4]--,t[2]--,ret++;
        if(t[3]%3==0&&t[1]+t[2]<=1)
            while(t[3]>2)t[3]-=3,ret+=2;//3=2+1,出三带二,三带一
         while(t[3]&&t[2])t[3]--,t[2]--,ret++;
         while(t[3]&&t[1])t[3]--,t[1]--,ret++;
         //还剩3和4
         while(t[4]>1&&t[3])t[4]-=2,t[3]--,ret+=2;//4=2+2,出四带二和三带二
         while(t[3]>1&&t[4])t[3]-=2,t[4]--,ret+=2;//4=2+2,出2*三带二
         while(t[3]>2)t[3]-=3,ret+=2;//3=2+1,出三带二和三带一
         while(t[4]>1)t[4]-=2,ret++;//4=2+2,出四带二对
         if(wz&&t[1]>=2)return ret+t[4]+t[3]+t[2]+t[1]-1;
         else return  ret+t[4]+t[3]+t[2]+t[1];
    }
    void dfs(int u)//顺子 
    {
        if(u>ans)return;
        int tmp=calc();
        if(u+tmp<ans)ans=u+tmp;
        for(int i=2,j;i<=13;i++)
        {
            for(j=i;j<=13;j++)if(a[j]<3)break;
            j--;
            if(j-i+1<2)continue;
            for(int k=j;k>=i+1;k--)
            {
                for(int l=i;l<=k;l++)a[l]-=3;
                dfs(u+1);
                for(int l=i;l<=k;l++)a[l]+=3;
            }
        }
        for(int i=2,j;i<=13;i++)
        {
            for(j=i;j<=13;j++)if(a[j]<2)break;
            j--;
            if(j-i+1<3)continue;
            for(int k=j;k>=i+2;k--)
            {
                for(int l=i;l<=k;l++)a[l]-=2;
                dfs(u+1);
                for(int l=i;l<=k;l++)a[l]+=2;
            }
        }
        for(int i=2,j;i<=13;i++)
        {
            for(j=i;j<=13;j++)if(!a[j])break;
            j--;
            if(j-i+1<5)continue;
            for(int k=j;k>=i+4;k--)
            {
                for(int l=i;l<=k;l++)a[l]--;
                dfs(u+1);
                for(int l=i;l<=k;l++)a[l]++;
            }
        }
    }
    int main()
    {
        scanf("%d%d",&T,&n);
        while(T--)
        {
            memset(a,0,sizeof a);
            for(int i=1,x,y;i<=n;i++)
            {
                scanf("%d%d",&x,&y);
                if(x==1)x=13;
                else if(x)x--;
                a[x]++;
            }
            ans=inf; dfs(0);
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Leetcode 15. 3Sum
    本周学习小结(01/07
    面试总结之Data Science
    学习笔记之MongoDB
    本周学习小结(13/05
    Django知识点总结
    Django【进阶篇 】
    Django【基础篇】
    如何拿到半数面试公司Offer——我的Python求职之路(转载)
    Django框架(三)
  • 原文地址:https://www.cnblogs.com/Zinn/p/9394486.html
Copyright © 2011-2022 走看看