• 【NOIP2015】斗地主 D1 T3 及 增强版 (送命题)


    恶心送命模拟题
    暴搜顺子,DP预处理剩下的。 由于官方数据太水,很多情况没有讨论的都能过普通版本,想要测试自己代码正确性的同学们可以交交这道题,有很多dalao给出了hack数据 : Luogu P2540 斗地主 增强版 传送门

    具体细节见代码注释
    AC code:

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 25;
    int n, cnt[15], p[5], Ans, dp[6][8][12][24];
    // 14 A
    // 0 king
    
    template<class T>inline bool chkmin(T &x, T y) { return y < x ? x = y, 1 : 0; }
    
    inline int solve(int i, int j, int k, int w, int king)
    {
    	if(king == 0) return dp[i][j][k][w];
    	if(king == 1) return dp[i][j][k][w+1]; // 单打
    	return min(dp[i][j][k][w] + 1,  dp[i][j][k][w+2]); //王炸 + 单打
    }
    
    int need[4] = { 0, 5, 3, 2 };
    
    void dfs(int now)
    {
    	if(now >= Ans) return;
    	memset(p, 0, sizeof p); //注意清零
    	for(int i = 2; i <= 14; i++) p[cnt[i]]++; //统计 4 3 2 1 个的
    	chkmin(Ans, now + solve(p[4], p[3], p[2], p[1], cnt[0]));
    	for(int len = 1; len <= 3; len++) //枚举顺子每个数字出现次数
    		for(int i = 3, j; i <= 14; i++) //枚举起点
    		{
    			for(j = i; j <= 14 && cnt[j] >= len; j++) //枚举终点
    			{
    				cnt[j] -= len;
    				if(j - i + 1 >= need[len]) dfs(now+1);
    			}
    			while(--j >= i) cnt[j] += len;
    		}
    }
    
    void Pre() //DP预处理
    {
    	memset(dp, 0x3f, sizeof dp);
    	for(int i = 0; i <= n/4; i++)
    		for(int j = 0; j <= n/3; j++)
    			for(int k = 0; k <= n/2; k++)
    				for(int w = 0; w <= n; w++) if(i*4 + j*3 + k*2 + w <= n)
    				{
    					dp[i][j][k][w] = i + j + k + w;
    					if(i)
    					{
    						if(w >= 2) chkmin(dp[i][j][k][w], dp[i-1][j][k][w-2] + 1);
    						if(k >= 2) chkmin(dp[i][j][k][w], dp[i-1][j][k-2][w] + 1);
    						chkmin(dp[i][j][k][w], dp[i-1][j][k][w] + 1); // 打 炸弹
    						chkmin(dp[i][j][k][w], dp[i-1][j][k+2][w]); //拆
    						chkmin(dp[i][j][k][w], dp[i-1][j][k+1][w+2]); //拆
    						chkmin(dp[i][j][k][w], dp[i-1][j][k+1][w+2]); //拆
    						chkmin(dp[i][j][k][w], dp[i-1][j][k][w+4]); //拆
    						chkmin(dp[i][j][k][w], dp[i-1][j+1][k][w+1]); //拆
    					}
    					if(j)
    					{
    						if(w >= 1) chkmin(dp[i][j][k][w], dp[i][j-1][k][w-1] + 1);
    						if(k >= 1) chkmin(dp[i][j][k][w], dp[i][j-1][k-1][w] + 1);
    						chkmin(dp[i][j][k][w], dp[i][j-1][k][w] + 1); //打 3 个
    						chkmin(dp[i][j][k][w], dp[i][j-1][k][w+3]); //拆
    						chkmin(dp[i][j][k][w], dp[i][j-1][k+1][w+1]); //拆
    					}
    					if(k) chkmin(dp[i][j][k][w], dp[i][j][k-1][w] + 1), chkmin(dp[i][j][k][w], dp[i][j][k-1][w+2]); // 打 2 个 + 拆
    					if(w) chkmin(dp[i][j][k][w], dp[i][j][k][w-1] + 1); //打 1 个
    				}
    }
    
    int main ()
    {
        int T, x, y;
    	scanf("%d%d", &T, &n);
    	Pre();
    	while(T--)
    	{
    		memset(cnt, 0, sizeof cnt);
    		
    		for(int i = 1; i <= n; i++)
    		{
    			scanf("%d%d", &x, &y);
    			if(x == 1) x = 14;// 把 A -> 14
    			cnt[x]++;
    		}
    		Ans = n; dfs(0);
    		printf("%d
    ", Ans);
    	}
    }
    
  • 相关阅读:
    app测试和web测试的相同点和不同点
    重写 和 重载
    23种设计模式总概括
    小程序webview跳转页面后没有返回按钮完美解决方案
    服务器配置https协议,三种免费的方法
    Android通过外部浏览器调用微信H5支付,Android+PHP详解
    vue多级复杂列表展开/折叠,全选/分组全选实现
    A very good RPC debugging session
    在WinForms中使用ActiveX
    Lauch Debugger automatically when start the process
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039479.html
Copyright © 2020-2023  润新知