洛谷P2668 斗地主 贪心+搜索

本文详细介绍了如何解决洛谷P2668斗地主问题。核心策略是,在排除顺子后,采用贪心算法确定最优的出牌顺序,如四带2对、四带2张等,接着用深度搜索处理不同类型的顺子,并在搜索过程中实施剪枝策略,避免无效搜索,当出牌次数超过最优解时终止搜索。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目连接
https://www.luogu.org/problem/show?pid=2668
只要出去顺子后,剩下的牌出的最优顺序是固定的,可以用贪心从四带2对,四带2张,三带1对,三带1张,剩下的对子和单张依次打出去,再特判一下王炸算一次出去就可以了。
然后就是对顺子进行搜索,单顺子,双顺子,三顺子一次搜索与回溯。
在搜索顺子过程中可以剪枝,如果当前出牌次数大于了ans,就不往下搜索了

 #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int t,n,ans,a,b;
int card[20],cnt[20];
void dfs(int x){
    if (x>ans) return ;
    memset(cnt,0,sizeof(cnt));
    int rest=0;
    for (int i=0;i<=14;i++)
    cnt[card[i]]++;
    while(cnt[4]){
        cnt[4]--;
        rest++;
        if (cnt[2]>=2)
        cnt[2]-=2;
        else if (cnt[1]>=2)
        cnt[1]-=2;
    }
    while(cnt[3]){
        cnt[3]--;
        rest++;
        if (cnt[2])
        cnt[2]--;
        else if (cnt[1])
        cnt[1]--;
    }
    if (card[0]&&card[1]&&cnt[1]>=2) rest--;
    rest+=cnt[1]+cnt[2];
    ans=min(ans,rest+x);
    for (int i=3;i<=15;i++){
      int j;
      for ( j=i;card[j]&&j<=14;j++)
         {
            card[j]--;
            if (j-i+1>=5)
            dfs(x+1);
         }
        while(j>i) card[--j]++;
    }
    for (int i=3;i<=15;i++){
        int j;
        for (j=i;card[j]>=2&&j<=14;j++)
        {
            card[j]-=2;
            if (j-i+1>=3)
            dfs(x+1);
        }
        while(j>i) card[--j]+=2;
    }
    for (int i=3;i<=15;i++){
        int j;
       for ( j=i;card[j]>=3&&j<=14;j++)
        {
            card[j]-=3;
            if (j-i+1>=2)
            dfs(x+1);
        }
        while(j>i) card[--j]+=3;
    }
}
int main(){
    cin>>t>>n;
    while(t--){
        memset(card,0,sizeof(card));
        ans=n;
        for (int i=1;i<=n;i++)
        {
        cin>>a>>b;
        if (a==0)
        card[b-1]++;
        else if (a==1) card[14]++;
        else card[a]++;
        }
        dfs(0);
        cout<<ans<<endl;
    }
    return 0;
}   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值