zoukankan      html  css  js  c++  java
  • [BZOJ 1028] [JSOI2007] 麻将 【枚举+贪心判断】

    题目链接:BZOJ - 1028

    题目分析

    枚举听的是哪种牌,再枚举成对的是哪种牌,再贪心判断:

    从1到n枚举每一种牌,如果这种牌的个数小于0,就返回不合法。

    将这种牌的张数 % 3, 剩下的只能和 i + 1, i + 2 这两种牌构成顺,所以 Num[i + 1] -= Num[i]; Num[i + 2] -= Num[i];

    牌的种类要枚举到 n + 2,因为第 n - 1 和第 n 种牌可能会减掉 n + 1,n + 2 的牌。

    代码

    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    
    const int MaxN = 400 + 5;
    
    int n, m, Top;
    int Cnt[MaxN], Num[MaxN], Ans[MaxN];
    
    int main() 
    {
    	scanf("%d%d", &n, &m);
    	int a;
    	for (int i = 1; i <= 3 * m + 1; ++i) 
    	{
    		scanf("%d", &a);
    		++Cnt[a];
    	}
    	bool Flag;
    	for (int i = 1; i <= n; ++i) 
    	{
    		for (int j = 1; j <= n + 2; ++j) Num[j] = Cnt[j];
    		++Num[i];
    		for (int j = 1; j <= n; ++j)
    		{
    			if (Num[j] < 2) continue;
    			Num[j] -= 2;
    			Flag = true;
    			for (int k = 1; k <= n + 2; ++k) 
    			{
    				if (Num[k] < 0) 
    				{
    					Flag = false;
    					break;
    				}
    				Num[k] %= 3;
    				Num[k + 1] -= Num[k];
    				Num[k + 2] -= Num[k];
    			}
    			if (Flag) 
    			{
    				Ans[++Top] = i;
    				break;
    			}
    			for (int k = 1; k <= n + 2; ++k) Num[k] = Cnt[k];
    			++Num[i];
    		}
    	}
    	if (Top == 0) printf("NO
    ");
    	else 
    	{
    		for (int i = 1; i <= Top - 1; ++i) printf("%d ", Ans[i]);
    		printf("%d
    ", Ans[Top]);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Pagodas
    Bazinga
    取石子问题
    Sudoku Killer(hdu 1426 数独)
    欧拉函数
    CCPC Ancient Go
    ZZNU 1992: 情人节的尴尬
    fzu Problem 2128 最长子串(KMP + strstr 经典好题)
    POJ
    HDU
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4321419.html
Copyright © 2011-2022 走看看