首先想到4种颜色,不同的顺序,和上升下降,可以通过搜索枚举出来,然后知道当前这手牌的目标按dfs出的顺序的最终情况应该是多少。
接下来就是一个巧妙的想法了,既然可以随便抽牌移动到任何地方,那么每次操作就一定插到最后的位置。那么不要动的牌就是那些本来相对位置就正确的牌了。
而相对位置正确可以通过经典的lcs问题的二维DP解决,将最初情况和最终情况进行lcs,那么最长公共子序列就是相对位置正确的牌。答案就是n-ans了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxl 60
using namespace std;
int n,ans;
int up[5],ord[5];
int num[maxl];
int a[maxl],b[maxl],ini[maxl];
int f[maxl][maxl];
int l[5]={0,1,14,27,40};
int r[5]={0,13,26,39,52};
char ch[maxl];
bool in[maxl];
inline void prework()
{
int x;
for(int i=1;i<=n;i++)
{
scanf("%s",ch);
if(ch[0]>='2' && ch[0]<='9')
x=ch[0]-'2'+1;
else if(ch[0]=='T')
x=9;
else if(ch[0]=='J')
x=10;
else if(ch[0]=='Q')
x=11;
else if(ch[0]=='K')
x=12;
else
x=13;
if(ch[1]=='h')
x+=13;
else if(ch[1]=='d')
x+=26;
else if(ch[1]=='c')
x+=39;
ini[i]=x;
}
}
inline void calc()
{
int left,right;
for(int i=1;i<=4;i++)
{
if(up[ord[i]]==1)
{
left=l[ord[i]];
for(int j=(i-1)*13+1;j<=i*13;j++)
num[j]=left++;
}
else
{
right=r[ord[i]];
for(int j=(i-1)*13+1;j<=i*13;j++)
num[j]=right--;
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=52;j++)
if(ini[i]==num[j])
a[i]=j;
for(int i=1;i<=n;i++)
b[i]=a[i];
sort(b+1,b+1+n);
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(a[i]==b[j])
f[i][j]=f[i-1][j-1]+1;
f[i][j]=max(f[i][j],f[i-1][j]);
f[i][j]=max(f[i][j],f[i][j-1]);
}
ans=max(ans,f[n][n]);
}
void dfs(int k)
{
for(int i=1;i<=4;i++)
if(!in[i])
{
ord[k]=i;in[i]=true;
up[i]=1;
if(k==4)
calc();
else
dfs(k+1);
up[i]=0;
up[i]=2;
if(k==4)
calc();
else
dfs(k+1);
up[i]=0;
ord[k]=0;in[i]=false;
}
}
inline void mainwork()
{
ans=0;
memset(in,false,sizeof(in));
dfs(1);
}
inline void print()
{
printf("%d\n",n-ans);
}
int main()
{
while(~scanf("%d",&n))
{
prework();
mainwork();
print();
}
return 0;
}