HDU - 4352(デジタル圧縮状態DP + + LIS)

問題の意味

デジタルは、シークの数の範囲内で最も長いシーケンス桁区間k上昇します

説明

最初のいくつかのDPのアイデアによって導入された、DP伝達方程式:
(POS、...ステータス)DFSが累積DFS(POS-1、.stautselse ...)=
DPとしてDPアレイ缶メモレコード[POS] [ステータス] [ k]を、 メモkの理由は、kは、異なるアクセス満たすためである
0が存在しないことを表し、私の存在に対応するビットの数を表す二進数で圧縮された状態に、ステータスレコードが選択された位置posに数字のデジタル組み合わせの始まりです。
Stautusの方法は等価的LIS得られる、注目は、特定のアクセス・ビットの存在に正確ではないかもしれない、と等価であるが、最も長い配列の長さは変化しない上昇です。
これにより最後の数字は、いくつかの方法の結果は、上昇サブシーケンスの最長数の長さをkに等しいかどうか、数がここ-1位置決定決定DP除去なるれます。問題は、x = 0の使用を考慮することがないので、それを行うために他のデジタルDP通常の方法によれば、0をリードし、LICアルゴリズムに気づく、結果も大きく、最も長いサブシーケンス+1結果が得られ、1ビット0に登場します。

#include <cstdio> 
#include <cstring>
#define ll long long
using namespace std;
int k;
int dig[25];
ll dp[25][1<<10][11];
int changes(int s, int x){
	for(int i = x; i < 10; i++){
		if(s&(1<<i))
			return (s^(1<<i))|(1<<x);
	}
	return s|(1<<x);
	
} 
int getnum(int s){
	int ans = 0;
	while(s){
		if(s&1)
			ans++;
		s>>=1;
	}
	return ans;
}
ll dfs(int pos,int sta, int limit, int pre){
	if(pos == -1) return getnum(sta) == k;
	if(!limit && dp[pos][sta][k]!= -1) return dp[pos][sta][k];
	int top = limit? dig[pos]:9;
	ll ans = 0;
	for(int i = 0; i <= top; i++){
		ans += dfs(pos-1, (pre&&(i == 0))?0:changes(sta, i),limit&&(i == top), pre&&(i == 0));
	} 
	if(!limit) dp[pos][sta][k] = ans;
	return ans;
}

ll slove(ll x){
	int pos = 0;
	while(x){
		dig[pos++] = x%10;
		x /= 10; 
	}
	ll ans = dfs(pos-1,0,1,1);
	return ans;
}
int main(){
	int t;
	ll n, m; 
	memset(dp, -1, sizeof(dp));	
	scanf("%d", &t);
	int cont = 1;

	while(t--){
		scanf("%lld %lld %d", &n, &m, &k);
		printf("Case #%d: %lld\n", cont++, slove(m) - slove(n-1));
	}
	
	return 0;
}
公開された52元の記事 ウォンの賞賛2 ビュー856

おすすめ

転載: blog.csdn.net/qq_44714572/article/details/103929036