题意:扑克牌有4种花色{s,h,d,c}. 现在有n张扑克牌牌={花色,编号}.
要求:将同一种花色牌放在一起.并且同一花色中编号按从小到大或者从大到小顺序放.
操作:把某张牌插入任意两种牌中间,或者放到头尾.
n<=52.
问满足条件时 最少要用多少次操作?
假设只有一个类型花色. 那么将序列排序需要的最小操作次数为:n- LIS (排序后LIS=n,一次操作最多让LIS+1).
现在有4种花色. 暴力确定满足条件时的最终状态 O(4!*2^4).
先枚举4种花色的优先级,然后在二进制枚举是正序还是逆序.最后在求出最多有多少个不用操作的元素(序列的LIS).即可.
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int N=2e3+5;
string a;
char tmp[]="shdc23456789TJQKA";
pii card[N];
int n,perm[N],best[N];
bool card_less(pii a,pii b,int s){
return a.first==b.first? a.second<b.second^(s>>a.first&1):
perm[a.first]<perm[b.first];
}
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>a;
card[i]=pii(find(tmp,tmp+4,a[1])-tmp,find(tmp,tmp+17,a[0])-tmp);
}
for(int i=0;i<4;i++) perm[i]=i;
int res=n;
do{
for(int s=0;s<(1<<4);s++){
for(int i=n-1;i>=0;i--){
best[i]=1;
for(int j=i+1;j<n;j++){
if(card_less(card[i],card[j],s))
best[i]=max(best[i],best[j]+1);
}
res=min(res,n-best[i]);
}
}
}while(next_permutation(perm,perm+4));
cout<<res<<'\n';
return 0;
}