您的位置:首页 > 其它

洛谷P2668 斗地主 贪心+搜索

2017-07-10 17:32 387 查看
题目连接

https://www.luogu.org/problem/show?pid=2668

只要出去顺子后,剩下的牌出的最优顺序是固定的,可以用贪心从四带2对,四带2张,三带1对,三带1张,剩下的对子和单张依次打出去,再特判一下王炸算一次出去就可以了。

然后就是对顺子进行搜索,单顺子,双顺子,三顺子一次搜索与回溯。

在搜索顺子过程中可以剪枝,如果当前出牌次数大于了ans,就不往下搜索了

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int t,n,ans,a,b;
int card[20],cnt[20];
void dfs(int x){
if (x>ans) return ;
memset(cnt,0,sizeof(cnt));
int rest=0;
for (int i=0;i<=14;i++)
cnt[card[i]]++;
while(cnt[4]){
cnt[4]--;
rest++;
if (cnt[2]>=2)
cnt[2]-=2;
else if (cnt[1]>=2)
cnt[1]-=2;
}
while(cnt[3]){
cnt[3]--;
rest++;
if (cnt[2])
cnt[2]--;
else if (cnt[1])
cnt[1]--;
}
if (card[0]&&card[1]&&cnt[1]>=2) rest--;
rest+=cnt[1]+cnt[2];
ans=min(ans,rest+x);
for (int i=3;i<=15;i++){
int j;
for ( j=i;card[j]&&j<=14;j++)
{
card[j]--;
if (j-i+1>=5)
dfs(x+1);
}
while(j>i) card[--j]++;
}
for (int i=3;i<=15;i++){
int j;
for (j=i;card[j]>=2&&j<=14;j++)
{
card[j]-=2;
if (j-i+1>=3)
dfs(x+1);
}
while(j>i) card[--j]+=2;
}
for (int i=3;i<=15;i++){
int j;
for ( j=i;card[j]>=3&&j<=14;j++)
{
card[j]-=3;
if (j-i+1>=2)
dfs(x+1);
}
while(j>i) card[--j]+=3;
}
}
int main(){
cin>>t>>n;
while(t--){
memset(card,0,sizeof(card));
ans=n;
for (int i=1;i<=n;i++)
{
cin>>a>>b;
if (a==0)
card[b-1]++;
else if (a==1) card[14]++;
else card[a]++;
}
dfs(0);
cout<<ans<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  搜索 贪心