zoukankan      html  css  js  c++  java
  • 【PKUSC2018】主斗地

    其实是道很清蒸的题,大家觉得它毒瘤大概主要是因为斗地主

    题目链接:PKUSC2018 主斗地

    题意就免了吧……

    题解

    因为去掉了三和××网友的17张牌,我们写个代码爆搜一下九莲可能的牌有多少种。

    #include<bits/stdc++.h>
    using namespace std;
    
    int ans;
    int a[20], res[20];
    char s[20];
    
    int get(char c) {
    	if (c == 'T') return 10;
    	if (c == 'J') return 11;
    	if (c == 'Q') return 12;
    	if (c == 'K') return 13;
    	if (c == 'A') return 14;
    	if (c == '2') return 15;
    	if (c == 'w') return 16;
    	if (c == 'W') return 17;
    	return c - '0';
    }
    
    void dfs(int x, int now) {
    	if (now > 17) return;
    	if (x == 18) {
    		if (now == 17) ++ans;
    		return;
    	}
    	for (int i = 0; i <= res[x]; ++i) {
    		dfs(x + 1, now + i);
    	}
    }
    
    int main() {
    	while (~scanf("%s", s + 1)) {
    		ans = 0;
    		memset(a, 0, sizeof a);
    		for (int i = 4; i <= 15; ++i) {
    			res[i] = 4;
    		}
    		res[16] = res[17] = 1;
    		for (int i = 1; i <= 17; ++i) {
    			int x = get(s[i]);
    			++a[x];
    			--res[x];
    		}
    		dfs(4, 0);
    		cout << ans << endl;
    	}
    }
    

    大致估计一下

    456789TJQKA456789

    应该是九莲的可能牌型数较多的一种输入,而这种九莲的可能牌型也只有1626841种。

    我们先搜出九莲的牌,暴力check是否可行。

    第一档部分分:输入数据中每种牌只出现最多只出现两次。这种情况下显然只有单牌是有用的,其余顺子对子都可以当做单牌打出。直接扫一下就OK。

    第二档部分分:每种牌最多出现三次。有用牌型只能是单牌,三带一,三带二。先爆搜出九莲哪些牌三张一起打出,以及对应的××网友用什么牌接,然后枚举这里面带了多少对子和单张,把九莲最大的牌和××网友最小的牌贪心带掉就好了。

    正解:还需要考虑四带二,和上一种本质相同,直接看代码吧。

    #include<bits/stdc++.h>
    using namespace std;
    
    char s[20];
    int ans, flag, a[20], b[20];
    int res[20];
    
    int get(char c) {
    	if (c == 'T') return 10;
    	if (c == 'J') return 11;
    	if (c == 'Q') return 12;
    	if (c == 'K') return 13;
    	if (c == 'A') return 14;
    	if (c == '2') return 15;
    	if (c == 'w') return 16;
    	if (c == 'W') return 17;
    	return c - '0';
    }
    
    void check2(int sg, int db) {
    	static int c[20], d[20];
    	for (int i = 4; i <= 17; ++i) {
    		c[i] = b[i];
    		d[i] = a[i];
    	}
    	for (int i = 4, j = 17; i <= 17 && db; ++i) {
    		while (d[i] >= 2 && db) {
    			while (j && c[j] < 2) --j;
    			if (c[j] >= 2) {
    				--db;
    				d[i] -= 2;
    				c[j] -= 2;
    			}
    			else break;
    		}
    	}
    	for (int i = 4, j = 17; i <= 17 && sg; ++i) {
    		while (d[i] >= 1 && sg) {
    			while (j && c[j] < 1) --j;
    			if (c[j] >= 1) {
    				--sg;
    				d[i] -= 1;
    				c[j] -= 1;
    			}
    			else break;
    		}
    	}
    	for (int i = 4, j = 4; i <= 17; ++i) {
    		while (c[i] > 0) {
    			while (d[j] == 0 && j <= 17) ++j;
    			if (d[j] > 0 && j > i) {
    				--c[i];
    				--d[j];
    			}
    			else return;
    		}
    	}
    	flag = 1;
    }
    
    void dfs2(int x, int tr, int fr, int A, int B) {
    	if (flag) return;
    	if (A < 0 || B < 0) return;
    	if (x == 18) {
    		if (A == 0 && B == 0) {
    			for (int i = 0; i <= tr; ++i) {
    				check2(i + fr * 2, tr - i);
    			}
    		}
    		return;
    	}
    	dfs2(x + 1, tr, fr, A, B);
    	if (b[x] >= 3) {
    		b[x] -= 3;
    		dfs2(x + 1, tr + 1, fr, A + 1, B);
    		b[x] += 3;
    	}
    	if (b[x] >= 4) {
    		b[x] -= 4;
    		dfs2(x + 1, tr, fr + 1, A, B + 1);
    		b[x] += 4;
    	}
    	if (a[x] >= 3) {
    		a[x] -= 3;
    		dfs2(x + 1, tr, fr, A - 1, B);
    		a[x] += 3;
    	}
    	if (a[x] >= 4) {
    		a[x] -= 4;
    		dfs2(x + 1, tr, fr, A, B - 1);
    		a[x] += 4;
    	}
    }
    
    void check() {
    	flag = 0;
    	dfs2(4, 0, 0, 0, 0);
    	ans += flag;
    }
    
    void dfs(int x, int now) {
    	if (now > 17) return;
    	if (x == 18) {
    		if (now == 17) check();
    		return;
    	}
    	for (int i = 0; i <= res[x]; ++i) {
    		b[x] = i;
    		dfs(x + 1, now + i);
    		b[x] = 0;
    	}
    }
    
    int main() {
    	while (~scanf("%s", s + 1)) {
    		ans = 0;
    		memset(a, 0, sizeof a);
    		for (int i = 4; i <= 15; ++i) {
    			res[i] = 4;
    		}
    		res[16] = res[17] = 1;
    		for (int i = 1; i <= 17; ++i) {
    			int x = get(s[i]);
    			++a[x];
    			--res[x];
    		}
    		dfs(4, 0);
    		cout << ans << endl;
    	}
    }
    
  • 相关阅读:
    7. Spring验证、数据绑定和类型转换
    J2EE应用与移动互联网-写在前头
    IT基础设施资源的实践----写在前头
    JavaScript随笔记(一)基础概念以及变量类型
    js函数表达式
    js面形对象(2)
    js面向对象
    viPlugin安装破解
    Ubuntu12.04 使用中遇到的问题
    关于sizeof
  • 原文地址:https://www.cnblogs.com/Vexoben/p/11728809.html
Copyright © 2011-2022 走看看