bzoj 1028: [JSOI2007]麻将 (贪心)

题目描述

传送门

题解

枚举听牌和对子,然后剩下的牌贪心的去判定。
假设当前判断到i,那么cnt[i]先模3,然后让cnt[i+1]-=cnt[i],cnt[i+2]-=cnt[i],最后如果没有牌的数量<0,则成立。
注意对于还没有判断的牌的个数不能先模3,要不如果前面的牌需要利用这个牌形成对子的时候就不能构成了。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 10003
using namespace std;
int a[N],cnt[N],n,m,ans[N];
int main()
{
    scanf("%d%d",&n,&m);
    m=3*m+1;
    for (int i=1;i<=m;i++) {
        int x; scanf("%d",&x);
        cnt[x]++;
    }
    bool mark=false;
    for (int i=1;i<=n;i++) 
     for (int k=1;k<=n;k++)
      if (cnt[k]>=2||cnt[k]==1&&i==k){
        for (int j=1;j<=n;j++) {
         a[j]=(j==i?1:0);
         if (j==k) a[j]+=(cnt[j]-2);
         else a[j]+=cnt[j];
        }
        a[n+1]=a[n+2]=0;
        bool pd=true;
        for (int j=1;j<=n;j++){
           if (a[j]<0) {
             pd=false;
             break;
           }    
           a[j]%=3; a[j+1]-=a[j]; a[j+2]-=a[j];
        }
        if (a[n+1]<0||a[n+2]<0) pd=false;
        if (pd) {
         mark=true; ans[++ans[0]]=i;
         break;
        }
    }
    for (int i=1;i<=ans[0]-1;i++) printf("%d ",ans[i]); 
    if (ans[0]) printf("%d\n",ans[ans[0]]);
    if (!mark) printf("NO\n");
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值