P3064 [USACO12DEC]伊斯坦布尔的帮派 (模拟)

题目传送门

题意:

 一片草地,每次可以只可以让一种牛占领,问你怎样安排牛的次序

最后剩下的是1号牛,并且输出其数量

 

思路:

 看到n到100 ,所以可以(n^3)暴力,第一重遍历次序,第二枚举是哪只牛

第三个for验证

然后在验证可否这里,我们的目标是让1号牛留到最后,所以我们要尽可能让

其他牛打架,并且数量多的牛影响最大,要最小消去

 

代码:

#include<bits/stdc++.h>
using namespace std;
#define N 105
int n,m;
int a[N],b[N];
int gang,cow;

void fight(int &gang,int &cow,int j)//记录把j号牛加进来后场地上占领的牛的编号和牛的数量
{
    if(cow==0) gang=j;
    if(gang==j) cow++;
    else cow--;
}
int solve(int gang,int cow)//贪心地把数量多的牛去消去,看最后剩下的是不是1号牛
{
    for(int i=1;i<=m;i++) b[i]=a[i];
    sort(b+2,b+m+1);
    while(b[m])
    {
        for(int i=m;i>=2;i--)
        {
            fight(gang,cow,i);
            b[i]--;
            if(b[i]>=b[i-1]) break;
        }
    }
    for(int i=1;i<=b[1];i++)
        fight(gang,cow,1);
    if(gang==1) return cow;
    else return 0;
}
int main()
{
    while(~scanf("%d %d",&n,&m))
    {
        for(int i=1;i<=m;i++) scanf("%d",&a[i]);
        int num=solve(0,0);
        if(num==0)
        {
            puts("NO");
            continue;
        }
        puts("YES");
        printf("%d\n",num);
        for(int i=1;i<=n;i++)//枚举次数
        {
            int tmp_gang=gang;
            int tmp_cow=cow;
            for(int j=1;j<=m;j++)//枚举每次用的是那只牛
            {
                if(!a[j]) continue;
                a[j]--;
                fight(gang,cow,j);
                if(solve(gang,cow)==num)
                {
                    printf("%d\n",j);
                    break;
                }
                a[j]++;
                gang=tmp_gang;
                cow=tmp_cow;
            }
        }
    }
    return 0;
}
View Code

 

posted @ 2019-03-05 20:20  better46  阅读(259)  评论(0编辑  收藏  举报