题目分析
错误解法 1:搜索顺子,剩下的牌分成有 1 张,有 2 张,有 3 张,有 4 张。然后 4 张组尽可能带 1 张和 2 张,再用 3 张组带 1 张和 2 张。
HACK 数据 1:
1 8
3 1
3 1
3 1
3 1
4 1
4 1
4 1
4 1
正确答案:1
我的答案:2
错误解法 2:特判了错误解法 1 里面的情况。
HACK 数据 2:
1 22
5 1
5 1
5 1
5 1
9 1
9 1
12 1
12 1
12 1
10 1
11 1
11 1
11 1
11 1
2 1
2 1
2 1
3 1
6 1
6 1
6 1
8 1
正确答案:4
我的答案:5
错误解法 3:于是我就觉得如果遇到 1 张单牌 1 个对子 1 个三牌 2 个四张的情况,就这么组合出最优,然后我就这么写了。
HACK 数据 3:
1 17
5 1
5 1
5 1
5 1
9 1
9 1
12 1
12 1
12 1
10 1
11 1
11 1
11 1
11 1
3 1
3 1
4 1
正确答案:3
我的答案:4
正确解法:
先搜索顺子,然后再搜一次,枚举每种牌是按照 1 个一组,2 个一组,3 个一组还是 4 个一组出,再用错误解法 1 里面的贪心。
结果因为顺子剩下来的牌没有判断等原因又 WA 了两次才 AC……
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int read(){
int q=0;char ch=' ';
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')q=q*10+ch-'0',ch=getchar();
return q;
}
int card[17],js[6],n,T,ans,lg;
int cal(){//贪心处理出牌方式
int re=0,a=js[1],b=js[2],c=js[3],d=js[4],kl;
kl=min(a/2,d),a-=kl*2,d-=kl,re+=kl;
kl=min(b/2,d),b-=kl*2,d-=kl,re+=kl;
kl=min(a,c),a-=kl,c-=kl,re+=kl;
kl=min(b,c),b-=kl,c-=kl,re+=kl;
return re+a+b+c+d;
}
void work(int x,int num){//搜索怎么拆牌
if(x==14){ans=min(num+cal(),ans);return;}
if(!card[x]){work(x+1,num);return;}
if(card[x]==4){
++js[4];work(x+1,num);--js[4];
++js[3],++js[1];work(x+1,num);--js[3],--js[1];
js[2]+=2;work(x+1,num);js[2]-=2;
++js[2],js[1]+=2;work(x+1,num);--js[2],js[1]-=2;
js[1]+=4;work(x+1,num);js[1]-=4;
}
else if(card[x]==3){
++js[3];work(x+1,num);--js[3];
++js[1],++js[2];work(x+1,num);--js[1],--js[2];
js[1]+=3;work(x+1,num);js[1]-=3;
}
else if(card[x]==2){
++js[2];work(x+1,num);--js[2];
js[1]+=2;work(x+1,num);js[1]-=2;
}
else {++js[1];work(x+1,num);--js[1];}
}
void dfs(int x,int num){//搜索顺子
if(num>=ans)return;
if(x==14){work(1,num);return;}
int i,cnt,j;
for(i=x;i<=12;++i){
cnt=0;
for(j=i;j<=12;++j){
if(!card[j])break;
--card[j],++cnt;
if(cnt>=5)dfs(x+1,num+1);
}
while(j>i)--j,++card[j];
}
for(i=x;i<=12;++i){
cnt=0;
for(j=i;j<=12;++j){
if(card[j]<2)break;
card[j]-=2,++cnt;
if(cnt>=3)dfs(x+1,num+1);
}
while(j>i)--j,card[j]+=2;
}
for(i=x;i<=12;++i){
cnt=0;
for(j=i;j<=12;++j){
if(card[j]<3)break;
card[j]-=3,++cnt;
if(cnt>=2)dfs(x+1,num+1);
}
while(j>i)--j,card[j]+=3;
}
dfs(x+1,num);
}
int main()
{
freopen("lx.in","r",stdin);
freopen("lx.out","w",stdout);
int i,x,y;
T=read(),n=read();
while(T--){
memset(card,0,sizeof(card));
for(i=1;i<=n;++i){
x=read(),y=read();
if(x==1)++card[12];
else if(x==2)++card[13];
else if(!x)++card[0];
else ++card[x-2];
}
ans=14;
js[1]+=card[0],dfs(1,0);
js[1]-=card[0];if(card[0]==2)dfs(1,1);
printf("%d\n",ans);
}
return 0;
}
0 条评论