题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=2020
题目大意是给出一系列扑克牌的点数和花色,将它们按花色按顺序(正逆序都可以)排好,求最少移动次数。
看了解题思路才知道原来可以暴力枚举每种排列然后比较最长公共子列,然后我的枚举……真的相当暴力……
中间求LCS的地方开始只初始化了LCS[0][0]=0然后从0遍历到n-1,然后一直WA=_=
不过感觉最坑的地方还是扑克点数的排序原来是23456789TJQKA……
AC代码:
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<map>
using namespace std;
int n;
int a[55],b[55];
struct poke
{
int id,rank,type,order;
char suit;
}card[55];
bool cmp(poke a,poke b)
{
if(a.type!=b.type)
{
return a.type<b.type;
}
else
{
if(a.order==1)
{
return a.rank<b.rank;
}
else
{
return a.rank>b.rank;
}
}
}
int LCS_length(int A[55],int B[55])//求A和B的最长公共子列
{
int LCS[55][55];
for(int i=0;i<=n;i++)
{
LCS[i][0]=0;
LCS[0][i]=0;
}
for(int x=1;x<=n;x++)
{
for(int y=1;y<=n;y++)
{
if(A[x]==B[y])
{
LCS[x][y]=LCS[x-1][y-1]+1;
}
else
{
LCS[x][y]=max(LCS[x-1][y],LCS[x][y-1]);
}
}
}
return LCS[n][n];
}
int main()
{
map<char,int>p;
char s1[]="23456789TJQKA",s2[]="shdcshcdsdhcsdchschdscdhhsdchscdhdschdcshcsdhcdsdshcdschdhscdhcsdcshdchscshdcsdhchsdchdscdshcdhs";
char s3[]="0000000100100011010001010110011110001001101010111100110111101111";
for(int i=0;i<13;i++)
{
p[s1[i]]=i+1;
}
while(scanf("%d",&n)!=EOF)
{
char s[5];
for(int i=1;i<=n;i++)
{
scanf("%s",s);
card[i].id=i;
card[i].rank=p[s[0]];
card[i].suit=s[1];
}
int ans=1e9;
for(int i=1;i<=n;i++)
{
a[i]=i;
}
for(int i=0;i<24;i++)
{
for(int j=0;j<4;j++)
{
p[s2[i*4+j]]=j+1;
}
for(int j=1;j<=n;j++)
{
card[j].type=p[card[j].suit];
}
for(int t=0;t<16;t++)
{
for(int j=1;j<=n;j++)
{
card[j].order=s3[4*t+card[j].type-1]-'0';
}
sort(card+1,card+n+1,cmp);
for(int j=1;j<=n;j++)
{
b[j]=card[j].id;
//printf("%d %d %d\n",card[j].id,card[j].type,card[j].order);
}
//system("pause");
ans=min(ans,n-LCS_length(a,b));
}
}
printf("%d\n",ans);
}
return 0;
}