Card Hand Sorting
题解思路:给你一副牌,没有大小王,同一种花色的牌要放在一起,同种花色的牌可以升序也可以降序,问我们需要移动牌的最少次数。
刚开始只想到了要用到最长公共子序列,然后就没有思路了。
后来看了题解才明白。
因为牌只有52张花色只有四种,每种花色内部可以升序或者降序,
所以我们就枚举所有花色的相对位置并且枚举当前花色是升序还是降序
总共有384种情况。
然后对于每一种情况我们求一次lcs这些就是不需要移动的,剩下的每一张牌我们只需要移动一次就能移到他的位置。
这里求lcs的过程写的麻烦了,只要记录新加一个pos变量,然后判断相对位置就可以了。
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<algorithm>
#include<cstring>
using namespace std;
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define sca(x) scanf("%d",&x)
#define per(i,j,k) for(int i=j;i>=k;i--)
#define inf 0x3f3f3f3f
#define LL long long
#define N 1006000
#define inf 0x3f3f3f3f
map<char,int>mmp,R;
int n;
struct node
{
int v,type,Rank,flag;//1升0降
friend bool operator <(node x,node y)
{
if(x.Rank==y.Rank)
{
return x.flag==1?x.v<y.v:x.v>y.v;
}
else return x.Rank<y.Rank;
}
}a[60],b[60];
void init()
{
mmp['s']=1,mmp['h']=2;
mmp['d']=3,mmp['c']=4;
int cnt=1;
for(int i=2;i<=10;i++)
{
R['0'+i]=cnt++;
}
R['T']=cnt++;
R['J']=cnt++;
R['Q']=cnt++;
R['K']=cnt++;
R['A']=cnt++;
}
int vis1[5],vis2[5],sor[5];
int dp[55][55];
int ans=inf;
void solve()
{
rep(i,1,n)
{
a[i].Rank=sor[a[i].type];
a[i].flag=vis2[a[i].type];
}
sort(a+1,a+1+n);
memset(dp,0,sizeof(dp));
rep(i,1,n)
{
rep(j,1,n)
{
if(a[i].v==b[j].v&&a[i].type==b[j].type)
{
dp[i][j]=dp[i-1][j-1]+1;
}
else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
ans=min(ans,n-dp[n][n]);
}
void dfs(int step)
{
if(step==5)
{
solve();
}
rep(i,1,4)
{
if(!vis1[i])
{
sor[step]=i;
vis1[i]=1;
rep(j,0,1)
{
vis2[step]=j;
dfs(step+1);
}
vis1[i]=0;
}
}
}
int main()
{
sca(n);
init();
string s;
rep(i,1,n)
{
cin>>s;
a[i].v=R[s[0]];
b[i].v=a[i].v;
a[i].type=mmp[s[1]];
b[i].type=a[i].type;
}
dfs(1);
cout<<ans<<endl;
}