zoukankan      html  css  js  c++  java
  • hdu 4996 1~n排列LIS值为k个数

    http://acm.hdu.edu.cn/showproblem.php?pid=4996

    直接贴bc题解

    按数字1-N的顺序依次枚举添加的数字,用2N的状态保存在那个min数组中的数字,每次新添加数字可以根据位置计算出新的min数组。
    怎么快速计算呢?这里如果枚举N的位置是不可行的,这样2n的state记录的信息不够。很巧妙的思路是枚举放在当前位置的数字,比如说1-N-1的排列状态下,枚举第N位为K,那么1-N-1位的>=k的数字全加1,就得到了一个1-N的排列。
    当然这个算法是有问题的,但是由于求的是长度,所以所有j代表的状态并不能正确表示对应的上升序列,因为每个有值的dp[j]必然有j&1 == 1,但是却奇迹般的AC了..所以大致理解算法思想和AC原因但是这个算法的解释略有疑问...
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <string>
    #include <queue>
    #include <map>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define RD(x) scanf("%d",&x)
    #define RD2(x,y) scanf("%d%d",&x,&y)
    #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define clr0(x) memset(x,0,sizeof(x))
    typedef long long LL;
    const int maxn = 1<<20;
    int n,k;
    LL f[20][20],dp[maxn],tmp[maxn];
    
    int cal(int x)
    {
        int ans = 0;
        for(int i = 0;i < 20;++i)
            if((1<<i)&x)
                ans++;
        return ans;
    }
    void init () {
        dp[1] = f[1][1] = 1;
        for(int i = 1;i < 18;++i){
            for(int j = 0;j < (1<<i);++j)
                tmp[j] = dp[j];
            for(int j = 0;j < (1<<(i+1));++j)
                dp[j] = 0;
            for(int j = 0;j < (1<<i);++j)if(tmp[j]){
                for(int k = 0;k <= i;++k){
                    int tot = 0,c[20],st = 0;
                    for(int l = 0;l < i;++l){
                        if((1<<l) & j){
                            c[tot] = l;
                            if(c[tot] >= k)
                                c[tot]++;
                            tot++;
                        }
                    }
                    c[tot++] = k;
                    for(int l = 0;l < tot;++l){
                        if(c[l] > k){
                            c[l] = k;
                            break;
                        }
                    }
                    for(int l = 0;l < tot;++l){
                        st |= (1<<c[l]);
                    }
                    dp[st] += tmp[j];
                }
            }
            for(int j = 0;j < (1<<(i+1));++j)
                f[i+1][cal(j)] += dp[j];
        }
    }
    int main() {
        init();
        int _;RD(_);while(_--){
            RD2(n,k);
            printf("%I64d
    ",f[n][k]);
        }
        return 0;
    }


  • 相关阅读:
    Why "权限不够“?
    ASP程序快速生成Excel文件
    百家争鸣之-破冰(2005年年度总结)
    PostgreSQL最常见问题
    Delphi使用server组件控制excel的一点经验
    打造完美linux系统:常用软件安装
    QA杂想(2006年2月16日)
    java jdk / api
    Linux + Database
    eclipse dorado plugin
  • 原文地址:https://www.cnblogs.com/zibaohun/p/4046798.html
Copyright © 2011-2022 走看看