【问题描述】
【输入格式】
【输出格式】
共 T 行,每行一个整数表示打光第 i 组手牌的最少次数。
【防爆零代码】
枚举手牌组数少的时候打光的所有可能性(30分)
#include<iostream>
int x[20001],y[20001];
using namespace std;
int main()
{
freopen("landlords.in","r",stdin);
freopen("landlords.out","w",stdout);
int t,n;
cin>>t>>n;
for(int i=1;i<=t;i++)
{
for(int i=1;i<=n;i++)
cin>>x[i]>>y[i];
if(n==1)
cout<<"1"<<endl;
if(n==2)
{
if(x[1]==x[2]) cout<<"1"<<endl;
else cout<<"2"<<endl;
}
if(n==3)
{
if(x[1]==x[2]&&x[1]==x[3]) cout<<"1"<<endl;
else if(x[1]==x[2]||x[1]==x[3]||x[2]==x[3]) cout<<"2"<<endl;
else cout<<"3"<<endl;
}
if(n==4)
{
if(x[1]==x[2]&&x[1]==x[3]&&x[1]==x[4]) cout<<"1"<<endl;
else
if(x[1]==x[2]&&x[2]==x[3])
cout<<1<<endl;
else
if(x[1]==x[2]&&x[2]==x[4])
cout<<1<<endl;
else
if(x[1]==x[3]&&x[3]==x[4])
cout<<1<<endl;
else
if(x[2]==x[3]&&x[3]==x[4])
cout<<1<<endl;
else
if(x[1]==x[2]&&x[3]==x[4])
cout<<2<<endl;
else
if(x[1]==x[3]&&x[2]==x[4])
cout<<2<<endl;
else
if(x[1]==x[4]&&x[2]==x[3])
cout<<2<<endl;
else
if(x[1]==x[2])
cout<<3<<endl;
else
if(x[1]==x[3])
cout<<3<<endl;
else
if(x[1]==x[4])
cout<<3<<endl;
else
if(x[2]==x[3])
cout<<3<<endl;
else
if(x[2]==x[4])
cout<<3<<endl;
else
if(x[3]==x[4])
cout<<3<<endl;
else
cout<<4<<endl;
}
}
}
【正解】
1.花色在本题中无用
2.出牌顺序除了顺子之外对打完手牌次数无影响
3.如果不打顺子,打完手牌次数一定,所以dfs搜索出单顺子,双顺子,三顺子后的总步数,然后更新答案
4.王要单独出
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
int a[15],num[15];
int n,t,ans;
using namespace std;
int chupai()
{
memset(num,0,sizeof(num));
for(int i=0;i<=13;i++)
num[a[i]]++;
int tot=0;
while(num[4]&&num[2]>1)
{
num[4]--;
num[2]-= 2;
tot++;
}
while(num[4]&&num[1]>1)
{
num[4]--;
num[1]-=2;
tot++;
}
while(num[4]&&num[2])
{
num[4]--;
num[2]--;
tot++;
}
while(num[3] && num[2])
{
num[3]--;
num[2]--;
tot++;
}
while(num[3]&&num[1])
{
num[3]--;
num[1]--;
tot++;
}
return tot+num[1]+num[2]+num[3]+num[4];
}
void dfs(int step)
{
if(step>=ans)
{
return;
}
int temp=chupai();
if(temp+step<ans)
ans=temp+step;
for(int i=2;i<=13;i++)
{
int j=i;
while(a[j]>=3)
j++;
if(j-i>=2)
{
for(int j2=i+1;j2<=j-1;j2++)
{
for(int k=i;k<=j2;k++)
a[k]-=3;
dfs(step+1);
for(int k=i;k<=j2;k++)
a[k]+=3;
}
}
}
for(int i=2;i<=13;i++)
{
int j=i;
while(a[j]>=2)
j++;
if(j-i>=3)
{
for(int j2=i+2;j2<=j-1;j2++)
{
for(int k=i;k<=j2;k++)
a[k]-=2;
dfs(step+1);
for(int k=i;k<=j2;k++)
a[k]+=2;
}
}
}
for(int i=2;i<=13;i++)
{
int j=i;
while(a[j]>=1)
j++;
if(j-i>=5)
{
for(int j2=i+4;j2<=j-1;j2++)
{
for(int k=i;k<=j2;k++)
a[k]--;
dfs(step+1);
for(int k=i;k<=j2;k++)
a[k]++;
}
}
}
}
int main()
{
freopen("landlords.in","r",stdin);
freopen("landlords.out","w",stdout);
scanf("%d%d",&t,&n);
while(t--)
{
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
if(x==1)//转换A
x=13;
else
{
if(x!=0)
x--;
}
a[x]++;
}
ans=9999999;
dfs(0);
printf("%d\n",ans);
}
return 0;
}