2015多校第6场 HDU 5355 Cake 贪心,暴力DFS

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5355

题意:给你n个尺寸大小分别为1,2,3,…,n的蛋糕,要求你分成m份,要求每份中所有蛋糕的大小之和均相同,如果有解,输出“YES”,并给出每份的蛋糕数及其尺寸大小,否则输出“NO”

例如n=5,m=3,即大小尺寸分别为1,2,3,4,5的5个蛋糕,要求分成三份,那么解可以是第一份一个蛋糕,大小为5;第二份两个蛋糕,大小为1、4;第三份两个蛋糕,大小为2、3。这样每份大小之和均为5,满足题目要求。

解法:首先得放一下这个题解:http://blog.csdn.net/queuelovestack/article/details/47321211 写的很好,这个问题的关键点在于判断出有合法方案时,我们可以将这些蛋糕按照2*m为单位一组一组的分配,每个人拿当前这组的最大最小,次大次小。。。

然后做完这个过程直到剩余[0,4*m],这个看代码就知道了。对于这个区间的值就直接爆搜即可。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
typedef long long LL;
vector <int> ans[15];
LL sumv[15], cake[maxn];
bool vis[maxn];
LL n, m, dis, res;
//[0-4*m]的DFS

bool dfs(int cur, int sum, int pos)
{
    if(cur == m+1) return true;
    for(int i=res; i>=pos; i--){
        if(vis[i]) continue;
        if(sum+i==dis){
            cake[i]=cur;
            vis[i]=1;
            if(dfs(cur+1,0,1)) return true;
            vis[i]=0;
            return false;
        }
        else if(sum+i<dis){
            cake[i]=cur;
            vis[i]=1;
            if(dfs(cur,sum+i,i+1)) return true;
            vis[i]=0;
        }
    }
    return false;
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--){
        scanf("%lld%lld", &n,&m);
        memset(sumv, 0, sizeof(sumv));
        memset(vis, false, sizeof(vis));
        memset(cake, 0, sizeof(cake));
        for(int i=0; i<=m; i++){
            ans[i].clear();
        }
        LL sum = n*(n+1)/2;
        if(sum%m!=0){
            puts("NO");
            continue;
        }
        LL ave = sum/m;
        if(ave < n){
            puts("NO");
            continue;
        }
        puts("YES");
        res = n%(2*m);
        //23%(12)=11
        if(res!=0){
            res += 2*m;
            //res=11+12=23
            res = min(res, n);
        }
        //
        //23 6
        int a,b;
        for(int i=n; i>res; i-=(2*m)){
            for(int k=1; k<=m; k++){
                a=i-k+1,b=i-(2*m)+k;//
                //23 12
                //22 13
                //...
                ans[k].push_back(a);
                ans[k].push_back(b);
                sumv[k]+=a, sumv[k]+=b;
            }
        }
        dis = ave - sumv[1];
        dfs(1, 0, 1);
        for(int i=1; i<=res; i++){
            ans[cake[i]].push_back(i);
        }
        for(int i=1; i<=m; i++){
            int sz = ans[i].size();
            printf("%d", sz);
            for(int j=0; j<sz; j++){
                printf(" %d", ans[i][j]);
            }
            puts("");
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/spfa/p/7354809.html