• 【NOIP2015】斗地主(dfs)


    练练码力。
    如果没有顺子,显然最小出牌次数可以贪心,优先出四带二,然后三带一或三带二,最后出对拍和单牌。
    把大小王归到单排一类中,最后特判如果剩余的单排大于2,把这两张当成大小王一起出。
    枚举所有出顺子的情况,用三个dfs,其中:

    dfs(int now, int l, int tot, int times)
    //now 当前到了第几小的牌
    //l 当前顺子的长度
    //tot 当前已经出了几次牌
    //times 当前大小的顺子(三顺,二顺,单顺)重复搜索了几遍
    

    关于为什么要用用times记录并重复搜索:
    考虑这组牌

    [egin{aligned} 3quad4quad5quad6quad6quad7quad7quad8quad9quad10 end{aligned} ]

    显然答案为两次,分别是3到7,6到10,中间有重复的部分,所以需要重复搜索。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <queue>
    using namespace std;
    const int N = 30;
    const int h[] = {14, 12, 13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
    int n, ans = 1e9;
    int card[N];
    bool flag = false;
    void check(int tt) {
    	int t[5]; memset(t, 0, sizeof(t));
    	for(int i = 1; i <= 15; i++) {
    		t[card[i]]++;
    	}
    	while(t[4]) {
    		if(t[1] >= 2) {
    			t[4]--; t[1] -= 2; tt++; continue;
    		}	else if(t[2] >= 2) {
    			t[4]--; t[2] -= 2; tt++; continue;
    		} else if(t[2] >= 1) {
    			t[4]--; t[2]--; tt++; continue;
    		} else {
    			t[4]--; tt++; continue;
    		}
    	}
    	while(t[3]) {
    		if(t[1] >= 1) {
    			t[3]--; t[1]--; tt++; continue;
    		} else if(t[2] >= 1) {
    			t[3]--; t[2]--; tt++; continue;
    		} else {
    			t[3]--; tt++; continue;
    		}
    	}
    	while(t[2]) tt++, t[2]--;
    	if(flag && t[1] >= 2) {
    		t[1] -= 2; tt++;
    	}
    	tt += t[1];
    	ans = min(ans, tt);
    	return ;
    }
    void dfs2(int now, int l, int tot, int times) {
    	if(now == 13) {
    		if(l >= 5) {
    			if(times < 4) dfs2(1, 0, tot + 1, times + 1);
    			if(times == 4) check(tot + 1);
    		}
    		else if(l == 0) {
    			if(times < 4) dfs2(1, 0, tot, times + 1);
    			if(times == 4) check(tot);
    		}
    		return ;
    	}
    	if(card[now] >= 1) {
    		card[now] -= 1;
    		dfs2(now + 1, l + 1, tot, times);
    		card[now] += 1;
    		if(l >= 5) dfs2(now + 1, 0, tot + 1, times);
    	} else {
    		if(l >= 5) dfs2(now + 1, 0, tot + 1, times);
    	}
    	if(l == 0) dfs2(now + 1, 0, tot, times);
    }
    
    void dfs1(int now, int l, int tot, int times) {//2
    	if(now == 13) {
    		if(l >= 3) {
    			if(times < 4) dfs1(1, 0, tot + 1, times + 1);
    			if(times == 4) dfs2(1, 0, tot + 1, 0);
    		}
    		else if(l == 0) {
    			if(times < 4) dfs1(1, 0, tot, times + 1);
    			if(times == 4) dfs2(1, 0, tot, 0);
    		}
    		return ;
    	}
    	if(card[now] >= 2) {
    		card[now] -= 2;
    		dfs1(now + 1, l + 1, tot, times);
    		card[now] += 2;
    		if(l >= 3) dfs1(now + 1, 0, tot + 1, times);
    	} else {
    		if(l >= 3) dfs1(now + 1, 0, tot + 1, times);
    	}
    	if(l == 0) dfs1(now + 1, 0, tot, times);
    }
    
    void dfs(int now, int l, int tot, int times) {//3
    	if(now == 13) {
    		if(l >= 2) {
    			if(times < 4) dfs(1, 0, tot + 1, times + 1);
    			if(times == 4) dfs1(1, 0, tot + 1, 0);
    		}
    		else if(l == 0) {
    			if(times < 4) dfs(1, 0, tot, times + 1);
    			if(times == 4) dfs1(1, 0, tot, 0);
    		}
    		return ;
    	}
    	if(card[now] >= 3) {
    		card[now] -= 3; 
    		dfs(now + 1, l + 1, tot, times);
    		card[now] += 3;
    		if(l >= 2) dfs(now + 1, 0, tot + 1, times);
    	} else {
    		if(l >= 2) dfs(now + 1, 0, tot + 1, times);
    	}
    	if(l == 0) dfs(now + 1, 0, tot, times);
    }
    
    int main() {
    //	freopen("data.in", "r", stdin);
    	int T; scanf("%d%d", &T, &n);
    	while(T--) {
    		memset(card, 0, sizeof(card));
    		ans = n; flag = false;
    		for(int i = 1, x, y; i <= n; i++) {
    			scanf("%d%d", &x, &y);
    			if(x == 0 && y == 1) card[14]++;
    			else if(x == 0 && y == 2) card[15]++;
    			else card[h[x]]++;
    		}
    		if(card[14] && card[15]) flag = true;
    		dfs(1, 0, 0, 0);
    		printf("%d
    ", ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    hdu 4123 树形dp+rmq
    POJ 2761 Feed the dogs 求区间第k大 划分树
    hdu 4585 shaolin 平衡树
    *hdu 4616 Game 树形DP
    hdu 5379 Mahjong tree 树形DP入门
    CF 581F Contest Page 树形DP
    hdu 2778 LCR 模拟题
    hdu 2896 病毒侵袭 AC自动机
    hdu 2222 Keywords Search AC自动机模板题
    透过c的编程原则,来规范自己现在的一些编程习惯
  • 原文地址:https://www.cnblogs.com/mcggvc/p/14058839.html
Copyright © 2020-2023  润新知