您的位置:首页 > 其它

Light OJ 1060 nth Permutation (状压DP)

2016-02-04 20:57 387 查看
题意:给出一个n个字符的字符串(n<=20),求其全排列的第k个排列。

解析:先将字符串排序

状态S记录第i位的字符是否有效。

类比全排列的过程。dp[S]记录状态S中的有效字符组成的序列的排列个数。

根据这个就可以确定第k个排列所在的位置。(具体看代码)

:

[code]#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>

#define th(x) this->x=x
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;

char s[25],ans[25];
int n,top;
LL k,dp[1<<20];

LL dfs(int S,LL k){
if(!S) return 1;
if(dp[S]!=-1&&k>dp[S]) return dp[S];

int i,j;bool c[26];
LL res = 0;
for(i = 0;i < 26;i++) c[i] = false;
for(i = 0;i < n;i++){
if((S>>i&1)&&!c[s[i]-'a']){
c[s[i]-'a'] = true;
res += dfs(S^(1<<i),k-res);
if(res>=k){
ans[top++] = s[i];
break;
}
}
}
return dp[S] = res;
}

int main(){
int i,j,cas,T;
scanf("%d",&cas);
for(T = 1;T <= cas;T++){
scanf("%s%I64d",s,&k);
n = strlen(s);
sort(s,s+n);
int S,Ed = 1<<n;
dp[0] = 1;top = 0;
for(S = 1;S < Ed;S++) dp[S] = -1;
dfs(Ed-1,k);
printf("Case %d: ",T);
if(top != n) puts("Impossible");
else{
for(i = top-1;i>=0;i--) putchar(ans[i]);
putchar('\n');
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: