[贪心]hdu5355 多校联合第六场 Cake

来源:互联网 发布:linux怎么删除组 编辑:程序博客网 时间:2024/05/20 11:34

首先我们是能够知道每份蛋糕的尺寸的,利用
n*(n+1)/2m可以算出来,
如果不能整除的话,那么一定无解。

然后我们考虑如何构造一组解,对于一块蛋糕,我想到了一个贪心策咯,尽量选择最大块的蛋糕,因为如果能选但是不选这块蛋糕,那么也一定是通过选取小块的蛋糕来拼凑出这块蛋糕的大小,但是如果小的拼凑出了这块,那么就不能用于拼凑其他的蛋糕,显然选择最大的这块是最优的,因为他不可能被用来拼凑出其他的蛋糕。
所以当前选取它不会造成其他的蛋糕拼凑受影响,所以我们这样选取一定是正确的。

#include <iostream>#include <cstdio>#include<numeric>#include<cstring>#include<cmath>#include<vector>#include<set>#include<algorithm>using namespace std;const int MAXN = 100010;long long sum[MAXN];vector<int> V[15];bool used[MAXN];void initsum(){    memset(sum,0,sizeof sum);    sum[0] = 0;    for(int i = 1;i<=100000;i++)        sum[i] = i+ sum[i-1];    return ;}int main(){    int T,n,m;    initsum();    scanf("%d",&T);    while(T--)    {        memset(used,0,sizeof used);        for(int i = 1; i<=10;i++)            V[i].clear();        scanf("%d%d",&n,&m);        if (sum[n] % m != 0)        {            printf("NO\n");        }        else        {            for(int i = 1; i<=m;i++)            {                int average = sum[n] / m;                for(int j = n;j>=1;j--)                {                    if (average >= j && !used[j])                    {                        V[i].push_back(j);                        average -= j;                        used[j] = 1;                    }                    if (average == 0)                        break;                }            }            int flag = 1;            for(int i = 1; i<=n;i++)                if (used[i] == 0) flag = 0;            if (flag)            {            printf("YES\n");            for(int i = 1; i<=m;i++)            {                printf("%d ",V[i].size());                vector<int>::iterator it;                for(it = V[i].begin(); it != V[i].end()-1;it++)                    printf("%d ",*it);                printf("%d\n",*it);            }            }            else printf("NO\n");        }    }    return 0;}
0 0
原创粉丝点击