您的位置:首页 > 其它

4325. 【NOIP2015提高组Day1】斗地主

2018-01-21 15:50 148 查看

4325. 【NOIP2015提高组Day1】斗地主

https://jzoj.net/senior/#main/show/4325

15年提高组的题,看到标题我吓了一跳,但细细分析来,还是可以做的。

过流程(题目描述):



大致是说给你一些牌,按照上述出牌方式,最少几步可以出完所有牌。

一开始就想到了很平常的方法——dfs,但我们发现直接暴力会T,于是,观察数据:n是固定的,所以这题会有很多状态是一样的,我们便自然的想到了预处理。

首先看,除顺子外,其他出牌方式对点数都没有要求,只对数量有要求,所以大致的思路就是先预处理没有顺子的情况的出牌步数,然后暴力求顺子的状况,O(1)求解。

我们设f[i][j][k][l]表示还剩i种牌有4张,j种牌有3张,k种牌有2张,l种牌有1张的最小出牌步数。

于是就有除顺子外的9种转移:

int did(int a,int b,int c,int d)
{
int ss=a+b+c+d;
if (d>=1)
ss=min(ss,f[a][b][c][d-1]);
if (b>=1 && c>=1)
ss=min(ss,f[a][b-1][c-1][d]);
if (b>=1 && d>=1)
ss=min(ss,f[a][b-1][c][d-1]);
if (c>=1)
ss=min(ss,f[a][b][c-1][d]);
if (b>=1)
ss=min(ss,f[a][b-1][c][d]);
if (a>=1)
ss=min(ss,f[a-1][b][c][d]);
if (a>=1 && d>=2)
ss=min(ss,f[a-1][b][c][d-2]);
if (a>=1 && c>=2)
ss=min(ss,f[a-1][b][c-2][d]);
if (a>=1 && c>=1)
ss=min(ss,f[a-1][b][c-1][d]);
}
......
{
f[0][0][0][0]=0;
for (i=0;i<=n;i++)
for (j=0;j<=n;j++)
for (k=0;k<=n;k++)
for (l=0;l<=n;l++)
f[i][j][k][l]=min(did(i,j,k,l)+1,f[i][j][k][l]);
}


在此之后,我们可以递归1~3顺子的情况,每一种状态更新答案即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: