zoukankan      html  css  js  c++  java
  • [NOIp2015]斗地主

    Description

    Luogu2688
    给定一手牌,问最少几步把这手牌打完。

    Solution

    DP出散牌,暴力找顺子。

    由于顺子可能会出现多余的单牌,所以暴力的枚举如何出顺子才更优。

    DP就是一个暴力DP,没有什么有趣的地方,不过不要忘了拆牌。

    Code

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using std::min;
    
    const int N = 25;
    
    int f[N][N][N][N][3];
    int mx[N];
    int a[N];
    int my[N];
    int ans = 1000, n;
    
    void init() {
        f[0][0][0][0][0] = 0;
        for (int r = 0; r <= mx[5]; ++r) {
            for (int l = 0; l <= mx[4]; ++l) {
                for (int k = 0; k <= mx[3]; ++k) {
                    for (int j = 0; j <= mx[2]; ++j) {
                        for (int i = 0; i <= mx[1]; ++i) {
                            int x = 1000;
                            // 出散牌:
                            if (i) x = min(x, f[i-1][j][k][l][r]);
                            if (j) x = min(x, f[i][j-1][k][l][r]);
                            if (k) x = min(x, f[i][j][k-1][l][r]);
                            if (l) x = min(x, f[i][j][k][l-1][r]);
                            if (r) x = min(x, f[i][j][k][l][r-1]);
                            if (r>1) x = min(x, f[i][j][k][l][r-2]);
                            // 三带/拆三
                            if (k) {
                                if (i) x = min(x, f[i-1][j][k-1][l][r]);
                                if (j) x = min(x, f[i][j-1][k-1][l][r]);
                                if (r) x = min(x, f[i][j][k-1][l][r-1]);
                                if (r>1) x = min(x, f[i][j][k-1][l][r-2]);
                                x = min(x, f[i+1][j+1][k-1][l][r] - 1);
                            }
                            // 四带/拆四
                            if (l) {
                                if (i>1) x = min(x, f[i-2][j][k][l-1][r]);
                                if (i && r) x = min(x, f[i-1][j][k][l-1][r-1]);
                                if (r>1) x = min(x, f[i][j][k][l-1][r-2]);
                                if (j>1) x = min(x, f[i][j-2][k][l-1][r]);
                                if (j && r>1) x = min(x, f[i][j-1][k][l-1][r-2]);
                                if (j) x = min(x, f[i][j-1][k][l-1][r]);
                                if (l>1) x = min(x, f[i][j][k][l-2][r]);
                                x = min(x, f[i+1][j][k+1][l-1][r] - 1);
                            }
                            f[i][j][k][l][r] = min(x + 1, f[i][j][k][l][r]);
                        }
                    }
                }
            }
        }
    }
    
    void dfs(int x) {
        if (x > ans) return;
        for (int k = 1, flag; k <= 3; ++k) {
            for (int i = 1; i <= 12; ++i) {
                flag = 1;
                int len = 4 / k + 1;
                while (flag && i + len - 1 <= 12) {
                    for (int j = 1; j <= len; ++j) {
                        if (a[i+j-1] < k) {
                            flag = 0;
                            break;
                        }
                    }
                    if (!flag) break;
                    for (int j = 1; j <= len; ++j) {
                        a[i+j-1] -= k;
                    }
                    dfs(x+1);
                    for (int j = 1; j <= len; ++j) {
                        a[i+j-1] += k;
                    }
                    len++;
                }
            }
        }
        memset(my, 0, sizeof my);
        for (int i = 1; i <= 13; ++i) my[a[i]]++;
        my[5] = a[14];
        ans = min(ans, x + f[my[1]][my[2]][my[3]][my[4]][my[5]]);
    }
    
    int main() {
        memset(f, 0x3f, sizeof f);
        int t;
        scanf("%d%d
    ", &t, &n);
        mx[1] = n; mx[2] = n / 2; mx[3] = n / 3; mx[4] = n / 4; mx[5] = 2;
        init();
        while (t--) {
            ans = 1000;
            memset(a, 0, sizeof a);
            for (int i = 1, x, y; i <= n; ++i) {
                scanf("%d%d", &x, &y);
                if (x == 0) a[14]++;
                else if (x <= 2) a[11+x]++; 
                else a[x-2]++;
            }
            dfs(0);
            printf("%d
    ", ans);
        }
        return 0;
    }
    
  • 相关阅读:
    kafka与Rocketmq的区别【转】
    k8s故障解决干货文档链接
    利用local nginx搭建k8s-1.17.4高可用kubernetes集群
    生产gitlab还原步骤
    jenkins备份和还原
    ASP.NET Core3.1使用IdentityServer4中间件系列随笔(二):创建API项目,配置IdentityServer保护API资源
    使用Feign出现404错误问题
    高并发系统限流-漏桶算法和令牌桶算法
    框架-springmvc源码分析(二)
    框架-springmvc源码分析(一)
  • 原文地址:https://www.cnblogs.com/wyxwyx/p/noip201513.html
Copyright © 2011-2022 走看看