Card Hand Sorting 18中南多校第一场C题

一、题意

随机给你一堆牌(标准扑克牌),之后让你按照:
  第一优先规则:所有相同花色的在一起

  第二优先规则:所有相同花色的必须按照升序或者降序排列

问,你最少要拿出多少张牌插入到其他的地方以维持这个状况?

二、做法

考虑,4种花色,因而排列有A44(24种);

考虑升降续组合,为2^4=16种

因而所有合法最终状态共有24*16种状态,因而可以进行枚举。

对于变化次数有,n-LCS(i);

故,枚举取最大即可。

最大时间复杂度为:
52*52+14*16*52*log52;

(因为最大卡牌数量为52)

三、代码

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<stdio.h>
#include<stdlib.h>
#include<vector>
#include<string>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
#define veci vector<int>
#define pp pair<ll,ll>
#define vecp vector<pp>

const ll MAXN=233; 
int c[]={'c','h','s','d'};
bool state[4];
char control[24][4];
vector<char> que;
int times=0;

const int ENDD=16;
void dfs(int dep)
{
	if(dep == 4)
	{
		int len=que.size();
		for(int i=0;i<len;++i)
		{
			control[times][i]=que[i];
		}
		times++;
	}else{
		for(int i=0;i<4;++i)
		{
			if(state[i]==0)
			{
				state[i]=1;
				que.push_back(c[i]);
				dfs(dep+1);
				state[i]=0;
				que.pop_back();
			}
		}
	}
}
ll n;
class Card
{
	public:
		char color;
		int num;
		Card(){}
		Card(char a,int b):color(a),num(b){}
		Card(string str)
		{
			color = str[1];
			char tar = str[0];
			if(tar>='0'&&tar<='9')num=tar - '0';
			if(tar == 'T')num=10;
			if(tar == 'J')num=11;
			if(tar == 'Q')num=12;
			if(tar == 'K')num=13;
			if(tar == 'A')num=14;
		}
		const bool operator == (Card c)
		{
			return color==c.color&&num==c.num;
		}
};
bool cmp_1 (Card c1,Card c2)
{
	return c1.num<c2.num;
}

bool cmp_2(Card c1,Card c2)
{
	return c1.num>c2.num;
}

Card cards[MAXN];
Card arr[ENDD][24][MAXN];
Card tmp[4][MAXN];
int points[4];

int search_number(char tar)
{
	for(int i=0;i<4;++i)
	{
		if(tar == c[i])return i;
	}return -1;
}

int lcs(int a,int b)
{
	int dp[MAXN][MAXN];
	memset(dp,0,sizeof(dp));
	for(int i=0;i<n;++i)
	{
		for(int j=0;j<n;++j)
		{
			int x=i+1;int y=j+1;
			if(arr[a][b][i] == cards[j])
				dp[x][y]=dp[x-1][y-1]+1;
			else dp[x][y]=max(dp[x-1][y],dp[x][y-1]);
		}
	}

	return dp[n][n];
}

void init()
{
	memset(cards,0,sizeof(cards));
	memset(arr,0,sizeof(arr));
	memset(points,0,sizeof(points));
	int res=0;
	for(int i=0;i<n;++i)
	{
		string str;
		cin>>str;
		cards[i] = Card(str);
	}
	for(int i=0;i<n;++i)
	{
		for(int j=0;j<4;++j)
		{
			if(cards[i].color == c[j])
			{
				tmp[j][points[j]++]=cards[i];
				break;
			}
		}
	}	

	for(int i=0;i<24;++i)
	{
		int point=0;
		for(int j=0;j<4;++j)
		{
			
			char now = control[i][j];
			int number = search_number(now);
			int start=point;
			for(int k=0;k<points[number];++k)
			{
				for(int m=0;m<ENDD;++m)
				{
					arr[m][i][point]=tmp[number][k];
				}												
				
				point++;
			}
			for(int m=0;m<ENDD;++m)
			{
				int k = 1<<j;
				if(k&m)
				{
					sort(arr[m][i]+start,arr[m][i]+point,cmp_1);
				}else sort(arr[m][i]+start,arr[m][i]+point,cmp_2);
			}
		}
	}	

	for(int i=0;i<ENDD;++i)
	{
		for(int j=0;j<24;++j)
		{
			res=max(res,lcs(i,j));
		}
	}
	cout<<n-res<<endl;
	
}


int main()
{
	cin.sync_with_stdio(false);
	dfs(0);
	while(cin>>n)init();
	// cout<<3)<<endl;
	return 0;
}

  

posted @ 2018-04-04 16:26  六花的邪王真眼  阅读(144)  评论(0编辑  收藏  举报