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

时间:2023-03-09 12:55:39
Luogu2540 斗地主增强版(搜索+动态规划)

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

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

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int T,n,cnt[],f[][][][][],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=;i<=;i++)
if (cnt[i]>=&&cnt[i+]>=)
{
cnt[i]-=,cnt[i+]-=;dfs(k-,step+);
int t=i+;while (cnt[t+]>=) t++,cnt[t]-=,dfs(k-(t-i+)*,step+);
while (t>=i) cnt[t]+=,t--;
}
}
void twostraight(int k,int step)
{
for (int i=;i<=;i++)
if (cnt[i]>=&&cnt[i+]>=&&cnt[i+]>=)
{
cnt[i]-=,cnt[i+]-=,cnt[i+]-=;dfs(k-,step+);
int t=i+;while (cnt[t+]>=) t++,cnt[t]-=,dfs(k-((t-i+)<<),step+);
while (t>=i) cnt[t]+=,t--;
}
}
void onestraight(int k,int step)
{
for (int i=;i<=;i++)
if (cnt[i]&&cnt[i+]&&cnt[i+]&&cnt[i+]&&cnt[i+])
{
cnt[i]--,cnt[i+]--,cnt[i+]--,cnt[i+]--,cnt[i+]--;dfs(k-,step+);
int t=i+;while (t<&&cnt[t+]) t++,cnt[t]--,dfs(k-(t-i+),step+);
while (t>=i) cnt[t]++,t--;
}
}
void dfs(int k,int step)
{
int t[]={};
for (int i=;i<=;i++) if (cnt[i]) t[cnt[i]]++;
t[]=cnt[]+cnt[];
ans=min(ans,step+f[t[]][t[]][t[]][t[]][t[]]);
if (step+(k>)>=ans) return;
if (k==) 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,,sizeof(f));
f[][][][][]=;
for (int i=;i<=n;i++)
for (int x=;x<=i;x++)
for (int y=;y*<=i-x;y++)
for (int z=;z*<=i-x-y*;z++)
for (int t=;t*<=i-x-y*-z*;t++)
for (int g=;g<=min(,i-x-y*-z*-t*);g++)
{
if (x) update(f[x][y][z][t][g],f[x-][y][z][t][g]+);
if (y) update(f[x][y][z][t][g],f[x][y-][z][t][g]+);
if (y) update(f[x][y][z][t][g],f[x+][y-][z][t][g]+);
if (z) update(f[x][y][z][t][g],f[x][y][z-][t][g]+);
if (z) update(f[x][y][z][t][g],f[x][y+][z-][t][g]+);
if (z) update(f[x][y][z][t][g],f[x+][y][z-][t][g]+);
if (t) update(f[x][y][z][t][g],f[x][y][z][t-][g]+);
if (t) update(f[x][y][z][t][g],f[x][y][z+][t-][g]+);
if (t) update(f[x][y][z][t][g],f[x][y+][z][t-][g]+);
if (t) update(f[x][y][z][t][g],f[x+][y][z][t-][g]+);
if (g) update(f[x][y][z][t][g],f[x][y][z][t][g-]+);
if (g==) update(f[x][y][z][t][g],f[x][y][z][t][g-]+);
//part 1 only one
if (z&&x) update(f[x][y][z][t][g],f[x-][y][z-][t][g]+);
if (z&&y) update(f[x][y][z][t][g],f[x+][y-][z-][t][g]+);
if (z>=) update(f[x][y][z][t][g],f[x][y+][z-][t][g]+);
if (z&&g) update(f[x][y][z][t][g],f[x][y][z-][t][g-]+);
if (t&&y) update(f[x][y][z][t][g],f[x+][y-][z][t-][g]+);
if (t>=) update(f[x][y][z][t][g],f[x+][y][z+][t-][g]+);
if (t&&g) update(f[x][y][z][t][g],f[x][y][z][t-][g-]+);
//part 2 three with one
if (z&&y) update(f[x][y][z][t][g],f[x][y-][z-][t][g]+);
if (z>=) update(f[x][y][z][t][g],f[x+][y][z-][t][g]+);
if (z&&t) update(f[x][y][z][t][g],f[x][y+][z-][t-][g]+);
if (t&&y) update(f[x][y][z][t][g],f[x+][y-][z][t-][g]+);
if (t&&z) update(f[x][y][z][t][g],f[x+][t][z-][t-][g]+);
if (t>=) update(f[x][t][z][t][g],f[x+][y+][z][t-][g]+);
//part 3 three with two
if (t)
{
if (x>=) update(f[x][y][z][t][g],f[x-][y][z][t-][g]+);
if (x&&g) update(f[x][y][z][t][g],f[x-][y][z][t-][g-]+);
if (y) update(f[x][y][z][t][g],f[x][y-][z][t-][g]+);
if (y>=) update(f[x][y][z][t][g],f[x+][y-][z][t-][g]+);
if (y&&g) update(f[x][y][z][t][g],f[x+][y-][z][t-][g-]+);
if (z) update(f[x][y][z][t][g],f[x+][y][z-][t-][g]+);
if (z&&x) update(f[x][y][z][t][g],f[x-][y+][z-][t-][g]+);
if (z&&y) update(f[x][y][z][t][g],f[x+][y][z-][t-][g]+);
if (z>=) update(f[x][y][z][t][g],f[x][y+][z-][t-][g]+);
if (z&&g) update(f[x][y][z][t][g],f[x][y+][z-][t-][g-]+);
if (t>=) update(f[x][y][z][t][g],f[x][y+][z][t-][g]+);
if (t>=) update(f[x][y][z][t][g],f[x][y][z+][t-][g]+);
if (t>=&&x) update(f[x][y][z][t][g],f[x-][y][z+][t-][g]+);
if (t>=&&y) update(f[x][y][z][t][g],f[x+][y-][z+][t-][g]+);
if (t>=&&z) update(f[x][y][z][t][g],f[x][y+][z][t-][g]+);
if (t>=&&g) update(f[x][y][z][t][g],f[x][y][z+][t-][g-]+);
if (g>=) update(f[x][y][z][t][g],f[x][y][z][t-][g-]+);
//part 4 four with one
if (y>=) update(f[x][y][z][t][g],f[x][y-][z][t-][g]+);
if (z>=) update(f[x][y][z][t][g],f[x+][y][z-][t-][g]+);
if (y&&z) update(f[x][y][z][t][g],f[x+][y][z-][t-][g]+);
if (t>=&&z) update(f[x][y][z][t][g],f[x+][y+][z-][t-][g]+);
if (t>=) update(f[x][y][z][t][g],f[x][y][z][t-][g]+);
if (t>=) update(f[x][y][z][t][g],f[x][y+][z][t-][g]+);
//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,,sizeof(cnt));
for (int i=;i<=n;i++)
{
int x=read(),y=read();
if (x==) cnt[y+]++;
else if (x==) cnt[]++;
else if (x==) cnt[]++;
else cnt[x-]++;
}
dfs(n,);
cout<<ans<<endl;
}
return ;
}