HDU4352 XHXJのLISのタイトルは、ビットDPを停止します

トピックリンク:http://acm.hdu.edu.cn/showproblem.php?pid=4352

タイトル効果:
要求間隔\([L、R] \ ) の長さの配列の範囲内の最大増加(最長増加サブ配列、LISと呼ぶ)\(K \)量数。

例えば:
\(123 \)唯一のLIS \(123 \) それのLISの長さであるので、(3 \)\ ; \
(101 \) LISつのみ\(01 \)そのようLIS長は(2 \)\ \;
(132 \) LISが持っているの\(13 \)\(12 \) その結果、LISの長さ\(2 \)
今、あなたのすべての3つの数字\(L、R&LT、K \)は、あなたが間隔尋ねる\([L、R] \ ) LISの長さの範囲内で\(K \)どのように多くの数。

問題解決のアイデア:
使用してこのタイトルのデジタルDPをそれを解決するために。

しかし、私はもっと必要な前提条件を考える:あなたが持っているどのようにバイナリメソッドを使用してLISを解決することで、より深い理解を持っています!
が、これは必要ありませんが、それはあなたが、状態遷移の過程を理解するのに役立ちます。

リセット状態\(DP [POS] [STA ] [K] \) の手段、この電流の\(K \)

  • これは、ビット数に現在ある\(POS \)
  • LISの現在の状態\(STA \)

ときに数。

\(STA \)圧縮された状態のイデオロギーを伴う、彼は、組成物の中の要素現在のLISと述べました。

初期の開始時間\(STA \)(0000000000 \)\(10 \(0 \) )。

いくつかの段階で、
現在選択されている場合\(A [0] \) \([1] A \)\(A [3] \) 次いで、現在の状態が\(0000001011 \)
電流が選択された([2] \)\(\ [4])\\(\ [7]) 現在の状態が\(0010010100 \)

私たちは、たとえば、数に来る次の\(15234 \) DPの私たちのデジタルプロセスを実証します:

初期\(STA \)(0000000000 \)\ ;

追加\(1 \)を、その後の状態になり(0000000010 \)\ ;

追加(5 \)\、そして状態になり(\ 0000100010)\ ;

参加(2 \)\、そして状態になり(0000000110 \)\
注:これが最も重要な場所です!
なぜ参加(2 \)\の後に\(5 \)が位置に対応するにはなり\(0 \)それを?
ステータスは、ここにレコードがあるので、その状態に対応我々二部LIS
だけ接合\(5 \)状態である\(0000100010 \)の長さを構成するために追加された新しい要素を表す、\(2 \) LISのを、より大きくなければならない(1 \)\大きい、
長さを構成するために新たに追加された要素\(3 \) LISのは、より大きくなければならない(5 \)\大きいです。
参加するには(2 \)\、その後、状況は長さを構成するには、この時以来、大幅に変更されました\(2 \)だけよりも優れ、LISの\(2 \)それに大きな。

だから、現在の状態のために\(STA \)と数字を入れるビットの現在の数(I \)\
場合\(STA \)最初の\(I \)ビットが\(1 \) そして新しい状態がまだある\ (STA \)(LISとして存在する)I \(\);
場合\(STA \)(I \)は\である(0 \)\次に、:

  • 場合(STA \)は\(特にバイナリを強調するために参照していない)を超えないがあります(私は\)\大のビットです\(1 \)は、新しい状態ですsta | (1<<i)
  • そうでなければ、よりは、(I \)\大きい最小位置こと\(0 \) 最初\(I \)位置\(1 \)は、新しい状態です。

次のようにコードは次のとおりです。

#include <bits/stdc++.h>
using namespace std;
long long f[22][1030][10];
int n, k, a[22];
void init() {
    memset(f, -1, sizeof(f));
}
int new_sta(int pos, int sta, int i) {
    if (!sta && i==0 && pos>0) return 0;
    if (!(sta>>(i+1)) || (sta&(1<<i))) return sta | (1<<i);
    for (int k = k = i+1; k < 10; k ++) if (sta & (1<<k)) return (sta ^ (1<<k)) | (1<<i);
}
long long dfs(int pos, int sta, bool limit) {
    if (pos < 0) return __builtin_popcount(sta) == k ? 1 : 0;
    if (!limit && f[pos][sta][k] != -1) return f[pos][sta][k];
    int up = limit ? a[pos] : 9;
    long long tmp = 0;
    for (int i = 0; i <= up; i ++) {
        tmp += dfs(pos-1, new_sta(pos, sta, i), limit && i==up);
    }
    if (!limit) f[pos][sta][k] = tmp;
    return tmp;
}
long long get_num(long long x) {
    int pos = 0;
    while (x) {
        a[pos++] = x % 10;
        x /= 10;
    }
    return dfs(pos-1, 0, true);
}
int T;
long long L, R;
int main() {
    init();
    scanf("%d", &T);
    for (int cas = 1; cas <= T; cas ++) {
        scanf("%lld%lld%d", &L, &R, &k);
        printf("Case #%d: %lld\n", cas, get_num(R) - get_num(L-1));
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/quanjun/p/12000855.html