• NOIP2015Day1T3斗地主(DFS)


      这类题...真的写不动T T

      首先可以发现没有顺子的话出牌次数是一定的, 换句话说只有顺子会影响出牌次数。

      所以可以暴搜出所有顺子的方案, 搜完之后记忆化搜索求一下a张1张同色牌, b张2张同色牌,c张3张同色牌, d张4张同色牌的最少出牌次数, 注意搜索的时候b可以拆出2个a, c可以拆出1个a, 2个b, d可以拆除2个b或者1个a, 1个c, 然后剩下的直接搜就好了, 这个效率不会估T T

      所以求可行方案用记忆化搜索也是很快的...效率大概就是状态数...

    #include<iostream> 
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath> 
    #include<algorithm> 
    using namespace std;
    const int maxn=25, inf=1e9;
    int T, n, x, y;
    int f[maxn][maxn][maxn][maxn], cnt[maxn], cntsum[maxn];
    int least[4]={0, 5, 3, 2};
    inline void read(int &k)
    {
        int f=1; k=0; char c=getchar();
        while(c<'0' || c>'9') c=='-'&&(f=-1), c=getchar();
        while(c<='9' && c>='0') k=k*10+c-'0', c=getchar();
        k*=f;
    }
    int dfs(int a, int b, int c, int d)
    {
        if(~f[a][b][c][d]) return f[a][b][c][d];
        int ans=inf;
        if(b) ans=min(ans, dfs(a+2, b-1, c, d));
        if(c) ans=min(ans, dfs(a+1, b+1, c-1, d));
        if(d) ans=min(ans, min(dfs(a+1, b, c+1, d-1), dfs(a, b+2, c, d-1)));
        if(a && c) ans=min(ans, dfs(a-1, b, c-1, d)+1);
        if(b && c) ans=min(ans, dfs(a, b-1, c-1, d)+1);
        if(a>=2 && d) ans=min(ans, dfs(a-2, b, c, d-1)+1);
        if(b>=2 && d) ans=min(ans, dfs(a, b-2, c, d-1)+1);
        return f[a][b][c][d]=min(ans, a+b+c+d); 
    }
    int solve(int step)
    {
        int ans=inf;
        for(int i=1;i<=3;i++)
            for(int j=3;j<=14;j++)
            {
                int len=0;
                for(int k=j;k<=14;k++) if(cnt[k]>=i) len++; else break; 
                for(int k=j+least[i]-1;k<=j+len-1;k++)
                {
                    for(int l=j;l<=k;l++) cnt[l]-=i;
                    ans=min(ans, solve(step+1));
                    for(int l=j;l<=k;l++) cnt[l]+=i;
                }
            }
        cntsum[1]=cntsum[2]=cntsum[3]=cntsum[4]=0;
        for(int i=2;i<=14;i++) cntsum[cnt[i]]++;
        if(cnt[0]==2) ans=min(ans, step+1+dfs(cntsum[1], cntsum[2], cntsum[3], cntsum[4]));
        cntsum[1]+=cnt[0];
        ans=min(ans, step+dfs(cntsum[1], cntsum[2], cntsum[3], cntsum[4]));
        return ans;
    }
    int main()
    {
        memset(f, -1, sizeof(f)); 
        f[0][0][0][0]=0;
        read(T); read(n);
        while(T--)
        {
            memset(cnt, 0, sizeof(cnt));
            for(int i=1;i<=n;i++) read(x), read(y), cnt[x==1?14:x]++;
            printf("%d
    ", solve(0));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    内存对齐
    总结一下,一晃工作有一年了
    标准库中迭代器的关系
    反转迭代器和插入迭代器的区别
    MFC定时关机程序的实现3-最小化到托盘栏
    MFC定时关机程序的实现2-添加启动项到注册表
    MFC定时关机程序的实现1
    C++文件读写之对象的读写
    ADO之密码验证--3次错误就锁定『改进』
    ADO之密码验证--3次错误就锁定
  • 原文地址:https://www.cnblogs.com/Sakits/p/7795145.html
Copyright © 2020-2023  润新知