zoukankan      html  css  js  c++  java
  • P4050 [JSOI2007]麻将

    传送门

    怎么好像没什么人写 $dp$ ...?

    设 $f[i][j][k][0/1]$ 表示当前处理完前 $1$ 到 $i$ 的数,上一位开始的顺子有 $j$ 个,当前位开始的顺子有 $k$ 个,是否已经有雀头,的情况下能不能胡

    因为连续三个顺子其实等价于三个刻字,所以我们只要考虑顺子小于 $3$ 的情况,即 $j,k$ 都小于 $3$

    然后枚举下一位的顺子数量并把当前位的顺子补好,剩下的全做刻字,顺便处理一下雀头就行

    然后枚举每种可能的听牌,跑一遍 $dp$ 看看有没有解

    具体怎么 $dp$ 也挺好想的,看代码注释吧...

    复杂度 $O(不会算)$,反正跑得飞快

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<vector>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=507;
    int n,m,a[N];
    int f[N][3][3][2];
    bool work()
    {
        memset(f,0,sizeof(f));
        f[0][0][0][0]=1;
        for(int i=0;i<n;i++)//当前处理完第i位,考虑下一位
            for(int j=0;j<3;j++)//以上一位开头有j个顺子
                for(int k=0;k<3;k++)//当前为开头有k个顺子
                    for(int p=0;p<2;p++)//当前是否有雀头
                    {
                        if(!f[i][j][k][p]) continue;//剪枝
                        for(int l=0;l<=min(a[i+1]-j-k,2);l++)//枚举下一位顺子数量
                            if((a[i+1]-j-k-l)%3==0)//剩下的全做刻字
                                f[i+1][k][l][p]=1;
                        if(!p)//考虑留两个做雀头
                            for(int l=0;l<=min(a[i+1]-j-k-2,2);l++)//同上
                                if((a[i+1]-j-k-l-2)%3==0)
                                    f[i+1][k][l][1]=1;
                    }
        return f[n][0][0][1];//看看最后有没有解
    }
    vector <int> ans;
    int main()
    {
        n=read(),m=read();
        for(int i=1;i<=m*3+1;i++) a[read()]++;
        for(int i=1;i<=n;i++)//枚举听牌
        {
            a[i]++;
            if(work()) ans.push_back(i);
            a[i]--;
        }
        int len=ans.size();
        if(!len) { printf("NO
    "); return 0; }
        for(int i=0;i<len;i++) printf("%d ",ans[i]);
        printf("
    ");
        return 0;
    }
  • 相关阅读:
    谁把天才变成了魔兽
    NetBeans 时事通讯(刊号 # 35 Nov 20, 2008)
    Java Annotation 手册
    《程序设计实践》读书笔记一
    5分钟让你明白金融危机爆发原因
    NetBeans 6.5 正式版可以下载了!
    Java Annotation 入门
    有关睡觉的学问
    oracle sql日期比较:
    C++编写安全OCX,IE不弹出安全提示
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/11433012.html
Copyright © 2011-2022 走看看