[NOIP 2015] 斗地主

[题目链接]

         http://uoj.ac/problem/147

[算法]

         搜索,对于每一种状态,我们可以将其压缩成一个五进制数,用STL-map记录在其状态下的最少出牌次数

         在搜索时,我们可以采取一个优化 : 如果只剩下单牌,那么直接将单牌出完

[代码]

         

#include<bits/stdc++.h>
using namespace std;
#define MAXN 25
#define MAXT 10
#define MAXC 15
const int inf = 2e9;

int T,n;
int cnt[MAXC + 1];
map<long long,int> mp;

inline long long get_state()
{
    long long ret = 0;
    for (int i = 1; i <= 15; i++) ret = 1ll * ret * 5 + 1ll * cnt[i];
    return ret;
}
inline int dfs()
{
        int step = inf;
        long long state = get_state();
        bool flag = false;
        if (state == 0) return 0;
        if (mp.count(state)) return mp[state]; 
        for (int i = 1; i <= 11; i++)
        {
                if (cnt[i] >= 3 && cnt[i + 1] >= 3)
                {
                        for (int j = i + 1; j <= 12; j++)
                        {
                                if (cnt[j] >= 3)
                                {
                                        for (int k = i; k <= j; k++) cnt[k]    -= 3;
                                        step = min(step,dfs() + 1);
                                        flag = true;
                                        for (int k = i; k <= j; k++) cnt[k] += 3;
                                } else break;
                        }
                }
        }
        for (int i = 1; i <= 10; i++)
        {
                if (cnt[i] >= 2 && cnt[i + 1] >= 2 && cnt[i + 2] >= 2)
                {
                        for (int j = i + 2; j <= 12; j++)
                        {
                                if (cnt[j] >= 2)
                                {
                                        for (int k = i; k <= j; k++) cnt[k]    -= 2;
                                        step = min(step,dfs() + 1);
                                        flag = true;
                                        for (int k = i; k <= j; k++) cnt[k] += 2;
                                } else break;
                        }
                }
        }
        for (int i = 1; i <= 8; i++)
        {    
                if (cnt[i] >= 1 && cnt[i + 1] >= 1 && cnt[i + 2] >= 1 && cnt[i + 3] >= 1 && cnt[i + 4] >= 1)
                {
                        for (int j = i + 4; j <= 12; j++)
                        {
                                if (cnt[j] >= 1)
                                {
                                        for (int k = i; k <= j; k++) cnt[k]--;
                                        flag = true;
                                        step = min(step,dfs() + 1);
                                        for (int k = i; k <= j; k++) cnt[k]++;
                                } else break;
                        }
                }
        }
        for (int i = 1; i <= 13; i++)
        {
                if (cnt[i] >= 4)
                {
                        cnt[i] -= 4;
                        for (int j = 1; j <= 15; j++)
                        {
                                if (!cnt[j]) continue;
                                cnt[j]--;
                                for (int k = 1; k <= 15; k++)
                                {
                                        if (!cnt[k]) continue;
                                        cnt[k]--;
                                        flag = true;
                                        step = min(step,dfs() + 1);
                                        cnt[k]++;
                                }
                                cnt[j]++;
                        }
                        for (int j = 1; j <= 15; j++)
                        {
                                if (cnt[j] < 2) continue;
                                cnt[j] -= 2;
                                for (int k = 1; k <= 15; k++)
                                {
                                        if (cnt[k] < 2) continue;
                                        cnt[k] -= 2;
                                        flag = true;
                                        step = min(step,dfs() + 1);
                                        cnt[k] += 2;
                                }
                                cnt[j] += 2;
                        }
                        cnt[i] += 4;
                }
        }
        for (int i = 1; i <= 13; i++)
        {
              if (cnt[i] >= 3)
              {
                  cnt[i] -= 3;
                  for (int j = 1; j <= 13; j++)
                  {
                          if (cnt[j] >= 2)
                          {
                                  cnt[j] -= 2;
                                  flag = true;
                                  step = min(step,dfs() + 1);
                                  cnt[j] += 2;
                          }
                  }
                  cnt[i] += 3;
              }
        }
        for (int i = 1; i <= 13; i++)
        {
                if (cnt[i] >= 3)
                {
                    cnt[i] -= 3;
                    for (int j = 1; j <= 15; j++)
                    {
                        if (cnt[j] >= 1)
                        {
                              cnt[j]--;
                              flag = true;
                              step = min(step,dfs() + 1);
                              cnt[j]++;
                        }
                    }
                    cnt[i] += 3;
                }
        }
        for (int i = 1; i <= 13; i++)
        {
              if (cnt[i] >= 4)
              {
                    cnt[i] -= 4;
                    flag = true;
                    step = min(step,dfs() + 1);
                    cnt[i] += 4;
              }
        }
        for (int i = 1; i <= 13; i++)
        {
              if (cnt[i] >= 3)
              {
                    cnt[i] -= 3;
                    flag = true;
                    step = min(step,dfs() + 1);
                    cnt[i] += 3;
              }
        }
        for (int i = 1; i <= 13; i++)
        {
              if (cnt[i] >= 2)
              {
                    cnt[i] -= 2;
                    flag = true;
                    step = min(step,dfs() + 1);
                    cnt[i] += 2;
              }
        }
        if (cnt[14] >= 1 && cnt[15] >= 1)
        {
              cnt[14]--;
              cnt[15]--;
              flag = true;
              step = min(step,dfs() + 1);
              cnt[14]++;
              cnt[15]++; 
        }
        if (!flag)
        {
              step = 0;
              for (int i = 1; i <= 15; i++) step += cnt[i];
        }
        return mp[state] = step;
}

int main() 
{
        
        scanf("%d%d",&T,&n);
        mp.clear();
        while (T--)
        {
            memset(cnt,0,sizeof(cnt));
            for (int i = 1; i <= n; i++)
            {
                        int a,b;
                scanf("%d%d",&a,&b);
                if (a == 0 && b == 1) cnt[14]++;
                else if (a == 0 && b == 2) cnt[15]++;
                else if (a == 2) cnt[13]++;
                else if (a == 1) cnt[12]++;
                else cnt[a - 2]++;
            }
            printf("%d
",dfs());
            mp.clear();
        }
        
        return 0;
    
}
原文地址:https://www.cnblogs.com/evenbao/p/9498401.html