UVA 1262编码(第k字典序)

来源:互联网 发布:发淘宝链接如何粘贴 编辑:程序博客网 时间:2024/05/29 15:50

点击打开链接

我们先统计分别在每一列均在两个矩阵出现的字母,然后从小到大排好序。

对于第一个样例来说,我们得到ACDW、BOP、GMOX、AP、GSU

第一个字母无论以什么开头 后面都有3*4*2*3=72种可能 当k<=72时 以a开头  73<=k<=144时第一个字母为C

tot为后面的全排列 tot/=cnt[i] 则第i个字符因取第j个 j=k/tot (下取整,所以k-- 保证(72-1)/72 和(71-1)/72都为取a字符) k-=tot*j


#include <iostream>#include <algorithm>#include <set>#include <cstring>#include <map>#include <vector> using namespace std;const int N=10;char x[N][N],y[N][N]; int cnt[N];vector<char> v[N];void input(){for(int i=1;i<=6;i++){for(int j=1;j<=5;j++){cin>>x[i][j];}} for(int i=1;i<=6;i++){for(int j=1;j<=5;j++){cin>>y[i][j];}} }int init(){for(int i=1;i<=5;i++)v[i].clear();for(int col=1;col<=5;col++) //找到可能的密码 {for(int r1=1;r1<=6;r1++){for(int r2=1;r2<=6;r2++){if(x[r1][col]==y[r2][col]){v[col].push_back(x[r1][col]);}}} }for(int i=1;i<=5;i++){if(v[i].empty()) return 0;sort(v[i].begin(),v[i].end());unique(v[i].begin(),v[i].end());cnt[i]=0;//第i列有多少个while(cnt[i]<v[i].size()-1&&v[i][cnt[i]+1]>v[i][cnt[i]]){cnt[i]++;} cnt[i]++;}return 1;}int main(){int t;cin>>t;while(t--){int k;//第k小cin>>k;input();if(!init()){cout<<"NO"<<endl; continue;}int tot=1;for(int i=1;i<=5;i++)tot*=cnt[i];if(tot<k){cout<<"NO"<<endl;continue;} k--;//vector中下标从0开始  for(int i=1;i<=5;i++)//确定第i位上的密码{tot/=cnt[i];//后面的最大排列 //字典序x大于a开头最大,小于b开头最大 则x为以b开头. //k大于j-1开头的最大&&小于j开头最大 int j=k/tot;//下取整 cout<<v[i][j];k-=j*tot; }cout<<endl;}return 0;} 


0 0
原创粉丝点击