记录编号 210832 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [NOIP 2015]斗地主 最终得分 100
用户昵称 Gravatarstdafx.h 是否通过 通过
代码语言 C++ 运行时间 0.235 s
提交时间 2015-11-29 11:05:51 内存使用 0.29 MiB
显示代码纯文本
#define Rep for(int i=0;i<14;i++)

#define MAXN 20UL
#define MAXS 180UL

#include <cstdio>
#include <cstring>

int s[MAXN],t,n,mk[MAXS][MAXN],Ans,cnt;

inline int in(){
	int x=0,c=getchar();
	while(c<'0'||c>'9') c=getchar();
	for(;c>='0'&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	return x;
}

inline void Check(int t,int len,int num){
	for(int i=t,j=1;j<=len;j++,i++){
		if(i==14) i=1;
		if(s[i]<num) return;
	}
	++cnt;
	for(int i=t,j=1;j<=len;j++,i++){
		if(i==14) i=1;
		mk[cnt][i]=num;
	}
	return;
}

inline void ReadIn(){
	memset(s,0,sizeof(s));
	memset(mk,0,sizeof(mk));
	cnt=0;
	for(int i=1,a,c;i<=n;i++){
		a=in(),c=in();
		s[a]++;
	}
	for(int len=12;len>=2;len--) for(int i=3,r=15-len;i<=r;i++)
		Check(i,len,3);
	for(int len=12;len>=3;len--) for(int i=3,r=15-len;i<=r;i++)
		Check(i,len,2);
	for(int len=12;len>=5;len--) for(int i=3,r=15-len;i<=r;i++)
		Check(i,len,1);
	Rep if(s[i]>=4){
		for(int j=0;j<14;j++){
			if(i==j||(!s[j])) continue;
			for(int k=j+1;k<14;k++){
				if(i==k||(!s[k])) continue;
				++cnt;
				mk[cnt][i]=4;
				mk[cnt][j]=mk[cnt][k]=1;
			}
		}
		for(int j=0;j<14;j++){
			if(i==j||s[j]<2) continue;
			for(int k=j+1;k<14;k++){
				if(i==k||s[k]<2) continue;
				++cnt;
				mk[cnt][i]=4;
				mk[cnt][j]=mk[cnt][k]=2;
			}
		}
	}
	Rep if(s[i]>=3){
		for(int j=1;j<14;j++){
			if(i==j||s[j]<2) continue;
			++cnt;
			mk[cnt][i]=3;
			mk[cnt][j]=2;
		}
		for(int j=0;j<14;j++){
			if(i==j||(!s[j])) continue;
			++cnt;
			mk[cnt][i]=3;
			mk[cnt][j]=1;
		}
	}
	return;
}

inline int Rest(){
	int p=0;
	Rep if(s[i]) p++;
	return p;
}

inline void Div(int p,int num){
	Rep s[i]-=mk[p][i]*num;
	return;
}

inline void Res(int p){
	Rep s[i]+=mk[p][i];
	return;
}

inline int Min(int a,int b){
	return a<b?a:b;
}

inline int Cal(int p){
	int temp=n;
	Rep if(mk[p][i]){
		temp=Min(temp,s[i]/mk[p][i]);
	}
	return temp;
}

int dfs(int p,int step){
	if(step>=Ans) return 50L;
	int rest=Rest(),temp_ans,num;
	if(p>cnt) return rest;
	if(!rest) return 0;
	if(rest+step<Ans) Ans=rest+step;
	temp_ans=rest;
	num=Cal(p);
	Div(p,num);
	for(int i=num,tmp;i>=0;i--){
		if(i!=num) Res(p);
		tmp=dfs(p+1,step+i);
		if(tmp+i<temp_ans) temp_ans=tmp+i;
		if(step+temp_ans<Ans) Ans=step+temp_ans;
	}
	return temp_ans;
}

inline void Work(){
	Ans=Rest();
	printf("%d\n",dfs(1,0));
	return;
}

int main(){
	freopen("landlords.in","r",stdin);
	freopen("landlords.out","w",stdout);
	t=in(),n=in();
	for(int i=1;i<=t;i++) ReadIn(),Work();
	return 0;
}