• [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;
        
    }
  • 相关阅读:
    SMTP协议简介
    Debian
    TCP/IP协议基础
    CentOS(Community ENTerprise Operating System)
    IO
    【备忘】Windows网络命令行操作
    repeater中绑定dropdownlist事件
    MultipleActiveResultSets
    .NET UEditor使用方法
    Asp.net中时间格式化的几种方法
  • 原文地址:https://www.cnblogs.com/evenbao/p/9498401.html
Copyright © 2020-2023  润新知