gangs

农场里的生活很艰苦,而且当生活很艰苦,你必须坚强起来。奶牛们形成了编号为1到M的帮派。这些帮派一开始和睦相处了一段时间,但是现在失控了!

奶牛们在竞争一片大草地的控制权。奶牛之间的冲突发生在连续的若干分钟内。每一分钟有一只奶牛走进草地。如果此时草地上没有奶牛,那么这只新进去的奶牛所在的帮派就能占领这片草地。如果草地上已经被新进去的奶牛的帮派所占领了,那么这只奶牛就在草地里吃草。否则,一只属于正在占领草地的帮派的奶牛会跟新来的奶牛发生冲突。

这些发生在两只奶牛之间的冲突由吵架开始,然后两只奶牛就会发现他们的共同点比他们的不同点更多。然后两只奶牛发现他们各自的错误,就离开他们所在的帮派,走出草地,再去FJ的客栈里喝一杯冷牛奶。如果在某次冲突之后,草地里没有奶牛,那么没有帮派占领草地。

Bessie知道这些冲突是怎么发生的。她知道每一个帮派有几只奶牛。Bessie很想在所有冲突都发生完,每只奶牛要么在草地上,要么在FJ客栈里之后,让她所在的帮派占领这片草地。请你帮助Bessie判断她所在的帮派(编号为1)是否有可能占领草地。

如果有可能占领草地,Bessie想知道最后最多能有多少只奶牛是属于她所在的帮派的。输出这个数字和能让Bessie的帮派占领草地的字典序最小的方案(每分钟进入草地的奶牛的帮派编号的序列)。一个序列X字典序比序列Y小的意思是有某个k,X[k]

Input

第一行输入两个整数奶牛总数N(1<=N<=100),帮派总数M(1<=M<=N)。

第2..M+1行,第i+1行包括属于帮派i的奶牛数。每个帮派至少有1只奶牛。

Output

第1行,如果Bessie的帮派能占领草地,输出YES。否则输出NO。

第2行,如果Bessie的帮派能占领草地,输出最后草地上剩下的最大可能的奶牛数。

第3..2+N行,在第(i+2)行输出第i分钟进去的奶牛的帮派编号(按最小字典序)。

定义一个函数process()
它将除1帮派以外所有帮派按大小排序,然后每个帮派轮流放人,seq[]存人的顺序。
之后再将1帮派的人们塞到末尾
再定义个函数Calc()
根据seq[]计算1帮派在末尾存活的人数。

一开始对整体来一遍process() , Calc(),就可以知道1帮派最多能存活多少人,记Std_va人。
然后判合法性。
接着我们要求字典序最小。
考虑字符串贪心。
枚举i,j表示第i个位置,如果放j帮派情况,按此情况做一遍Process()与Calc(),若Calc()==Std_va则可以i位置放j帮派

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std ;

#define N 110 

int i , j , n , k , tot , maxi , m ;

int a[N] , seq[N]  ;

struct node {
    int ps , va ;
}tmp[N] ;

bool cmp( node a , node b ) {
    return a.va<b.va ;
}

void Process( int st ) {
    int i ;
    for( i=2 ; i<=m ; i++ ) tmp[i-1].va = a[i] , tmp[i-1].ps = i ;
    sort( tmp+1 , tmp+m , cmp ) ;
    for( i=m-1 ; tmp[m-1].va!=0 ;  ) {
        while( tmp[i-1].va==tmp[i].va ) i-- ;
        for( int j = m - 1 ; j>=i ; j-- ) {
            seq[st++] = tmp[j].ps , tmp[j].va-- ;
        }
    }
    for( i=1 ; i<=a[1] ; i++ ) seq[st++] = 1 ;
}

int Calc() {
    int Capt=-1 , num=0 ;
    for( int i=1 ; i<=n ; i++ ) {
        if( seq[i]!=Capt ) {
            if( num==0 ) Capt = seq[i] , num = 1 ; else num -- ;
        } else num ++ ;
    }
    if( Capt!=1 ) return -1 ; else return num ;
}

int main() {
    scanf("%d%d",&n,&m ) ;
    for( i=1 ; i<=m ; i++ ) scanf("%d",&a[i] ) ;
    Process( 1 ) ;
    int Standard_value = Calc() ;
    if( Standard_value==-1 ) {
        puts("NO" ) ;
        return 0 ;
    } 
    for( i=1 ; i<=n ; i++ ) { // Sweeping Postition
        for( j=1 ; j<=n ; j++ ) if( a[j]>0 ) {
            seq[i] = j ;
            a[j]-- ;
            Process( i+1 ) ;
            int Compare_va = Calc() ;
            if( Compare_va == Standard_value ) break ;
            a[j]++ ;
        }
    }   
    puts("YES" ) ;
    printf("%d\n",Standard_value ) ;
    for( i=1 ; i<=n ; i++ ) printf("%d\n",seq[i] ) ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值