您的位置:首页 > 其它

Luogu2540 斗地主增强版(搜索+动态规划)

2018-10-14 16:03 274 查看

  单纯的暴搜似乎还是很好写的,然而过不了。出完顺子之后答案是可以dp出来的,于是大力搜然后大力dp就好了。

  dp时强行讨论完了几乎所有拆牌情况,理性愉悦一发。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int T,n,cnt[20],f[24][13][9][7][3],ans;//1:2 2~12:3~K 13:A 14 15:ghost
void dfs(int k,int step);
void threestraight(int k,int step)
{
for (int i=2;i<=12;i++)
if (cnt[i]>=3&&cnt[i+1]>=3)
{
cnt[i]-=3,cnt[i+1]-=3;dfs(k-6,step+1);
int t=i+1;while (cnt[t+1]>=3) t++,cnt[t]-=3,dfs(k-(t-i+1)*3,step+1);
while (t>=i) cnt[t]+=3,t--;
}
}
void twostraight(int k,int step)
{
for (int i=2;i<=11;i++)
if (cnt[i]>=2&&cnt[i+1]>=2&&cnt[i+2]>=2)
{
cnt[i]-=2,cnt[i+1]-=2,cnt[i+2]-=2;dfs(k-6,step+1);
int t=i+2;while (cnt[t+1]>=2) t++,cnt[t]-=2,dfs(k-((t-i+1)<<1),step+1);
while (t>=i) cnt[t]+=2,t--;
}
}
void onestraight(int k,int step)
{
for (int i=2;i<=9;i++)
if (cnt[i]&&cnt[i+1]&&cnt[i+2]&&cnt[i+3]&&cnt[i+4])
{
cnt[i]--,cnt[i+1]--,cnt[i+2]--,cnt[i+3]--,cnt[i+4]--;dfs(k-5,step+1);
int t=i+4;while (t<13&&cnt[t+1]) t++,cnt[t]--,dfs(k-(t-i+1),step+1);
while (t>=i) cnt[t]++,t--;
}
}
void dfs(int k,int step)
{
int t[6]={0};
for (int i=1;i<=13;i++) if (cnt[i]) t[cnt[i]]++;
t[5]=cnt[14]+cnt[15];
ans=min(ans,step+f[t[1]][t[2]][t[3]][t[4]][t[5]]);
if (step+(k>0)>=ans) return;
if (k==0) return;
threestraight(k,step);
twostraight(k,step);
onestraight(k,step);
}
inline void update(int &x,int y){x=min(x,y);}
void dp()
{
memset(f,42,sizeof(f));
f[0][0][0][0][0]=0;
for (int i=1;i<=n;i++)
for (int x=0;x<=i;x++)
for (int y=0;y*2<=i-x;y++)
for (int z=0;z*3<=i-x-y*2;z++)
for (int t=0;t*4<=i-x-y*2-z*3;t++)
for (int g=0;g<=min(2,i-x-y*2-z*3-t*4);g++)
{
if (x) update(f[x][y][z][t][g],f[x-1][y][z][t][g]+1);
if (y) update(f[x][y][z][t][g],f[x][y-1][z][t][g]+1);
if (y) update(f[x][y][z][t][g],f[x+1][y-1][z][t][g]+1);
if (z) update(f[x][y][z][t][g],f[x][y][z-1][t][g]+1);
if (z) update(f[x][y][z][t][g],f[x][y+1][z-1][t][g]+1);
if (z) update(f[x][y][z][t][g],f[x+1][y][z-1][t][g]+1);
if (t) update(f[x][y][z][t][g],f[x][y][z][t-1][g]+1);
if (t) update(f[x][y][z][t][g],f[x][y][z+1][t-1][g]+1);
if (t) update(f[x][y][z][t][g],f[x][y+1][z][t-1][g]+1);
if (t) update(f[x][y][z][t][g],f[x+1][y][z][t-1][g]+1);
if (g) update(f[x][y][z][t][g],f[x][y][z][t][g-1]+1);
if (g==2) update(f[x][y][z][t][g],f[x][y][z][t][g-2]+1);
//part 1 only one
if (z&&x) update(f[x][y][z][t][g],f[x-1][y][z-1][t][g]+1);
if (z&&y) update(f[x][y][z][t][g],f[x+1][y-1][z-1][t][g]+1);
if (z>=2) update(f[x][y][z][t][g],f[x][y+1][z-2][t][g]+1);
if (z&&g) update(f[x][y][z][t][g],f[x][y][z-1][t][g-1]+1);
if (t&&y) update(f[x][y][z][t][g],f[x+2][y-1][z][t-1][g]+1);
if (t>=2) update(f[x][y][z][t][g],f[x+1][y][z+1][t-2][g]+1);
if (t&&g) update(f[x][y][z][t][g],f[x][y][z][t-1][g-1]+1);
//part 2 three with one
if (z&&y) update(f[x][y][z][t][g],f[x][y-1][z-1][t][g]+1);
if (z>=2) update(f[x][y][z][t][g],f[x+1][y][z-2][t][g]+1);
if (z&&t) update(f[x][y][z][t][g],f[x][y+1][z-1][t-1][g]+1);
if (t&&y) update(f[x][y][z][t][g],f[x+1][y-1][z][t-1][g]+1);
if (t&&z) update(f[x][y][z][t][g],f[x+2][t][z-1][t-1][g]+1);
if (t>=2) update(f[x][t][z][t][g],f[x+1][y+1][z][t-2][g]+1);
//part 3 three with two
if (t)
{
if (x>=2) update(f[x][y][z][t][g],f[x-2][y][z][t-1][g]+1);
if (x&&g) update(f[x][y][z][t][g],f[x-1][y][z][t-1][g-1]+1);
if (y) update(f[x][y][z][t][g],f[x][y-1][z][t-1][g]+1);
if (y>=2) update(f[x][y][z][t][g],f[x+2][y-2][z][t-1][g]+1);
if (y&&g) update(f[x][y][z][t][g],f[x+1][y-1][z][t-1][g-1]+1);
if (z) update(f[x][y][z][t][g],f[x+1][y][z-1][t-1][g]+1);
if (z&&x) update(f[x][y][z][t][g],f[x-1][y+1][z-1][t-1][g]+1);
if (z&&y) update(f[x][y][z][t][g],f[x+1][y][z-1][t-1][g]+1);
if (z>=2) update(f[x][y][z][t][g],f[x][y+1][z-2][t-1][g]+1);
if (z&&g) update(f[x][y][z][t][g],f[x][y+1][z-1][t-1][g-1]+1);
if (t>=2) update(f[x][y][z][t][g],f[x][y+1][z][t-2][g]+1);
if (t>=3) update(f[x][y][z][t][g],f[x][y][z+2][t-3][g]+1);
if (t>=2&&x) update(f[x][y][z][t][g],f[x-1][y][z+1][t-2][g]+1);
if (t>=2&&y) update(f[x][y][z][t][g],f[x+1][y-1][z+1][t-2][g]+1);
if (t>=2&&z) update(f[x][y][z][t][g],f[x][y+1][z][t-2][g]+1);
if (t>=2&&g) update(f[x][y][z][t][g],f[x][y][z+1][t-2][g-1]+1);
if (g>=2) update(f[x][y][z][t][g],f[x][y][z][t-1][g-2]+1);
//part 4 four with one
if (y>=2) update(f[x][y][z][t][g],f[x][y-2][z][t-1][g]+1);
if (z>=2) update(f[x][y][z][t][g],f[x+2][y][z-2][t-1][g]+1);
if (y&&z) update(f[x][y][z][t][g],f[x+1][y][z-1][t-1][g]+1);
if (t>=2&&z) update(f[x][y][z][t][g],f[x+1][y+1][z-1][t-2][g]+1);
if (t>=2) update(f[x][y][z][t][g],f[x][y][z][t-2][g]+1);
if (t>=3) update(f[x][y][z][t][g],f[x][y+2][z][t-3][g]+1);
//part 5 four with two
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("2540.in","r",stdin);
freopen("2540.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
T=read(),n=read();
dp();
while (T--)
{
ans=n;memset(cnt,0,sizeof(cnt));
for (int i=1;i<=n;i++)
{
int x=read(),y=read();
if (x==0) cnt[y+13]++;
else if (x==2) cnt[1]++;
else if (x==1) cnt[13]++;
else cnt[x-1]++;
}
dfs(n,0);
cout<<ans<<endl;
}
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: