洛谷P2668 斗地主 贪心+搜索

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

 #include
#include
#include
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<return 0;
}   

你可能感兴趣的:(贪心,搜索)