hdu 5355 Cake(构造+回溯)

题意:

给出一个蛋糕,切成1~n大小的n块,问能否在不继续切割的情况下拼凑出m等份。

解析:

首先可以求出这些蛋糕的总和n?(n+1)/2,如果总和sum%m != 0那么就不肯能被平分成m份,那么输出”NO”。

接下来计算平均数avg=sum/m,如果平均数avg < n的话,蛋糕是不可能用完的,同样也输出”NO”。

剩下的情况蛋糕是一定能拼成”YES”的,那么可以将这些蛋糕以2*m为单位一组一组的分配,每个人拿当前这组的最大和最小,次大和次小…..

直至拿到剩下[0,4?m]个蛋糕之间是停止。

这时候进行暴力求解,问题变成了1~n个数字,能否拼出,和相同的m个数字,这里直接暴力搜索dfs。

总结:

这题在比赛的时候special judge坏掉了,所以有很多wa的代码也ac了。后来数据加强了,以下这份代码是可以通过数据加强的代码。

my code

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define pb push_back
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
vector<int> ans[15];
int sumv[15], cake[N];
bool vis[N];
ll n, m;
ll sum, avg, res, dis;

void init() {
    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();
}

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] = true;
            if(dfs(cur+1, 0, 1))
                return true;
            vis[i] = false;
            return false;
        }else if(sum + i < dis) {
            cake[i] = cur;
            vis[i] = true;
            if(dfs(cur, sum+i, i+1))
                return true;
            vis[i] = false;
        }
    }
    return false;
}

int main() {
    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%lld%lld", &n, &m);
        init();

        if(n & 1) sum = (n + 1) / 2 * n;
        else sum = n / 2 * (n + 1);

        if(sum % m != 0 ) {
            puts("NO");
            continue;
        }
        avg = sum / m;
        if(avg < n) {
            puts("NO");
            continue;
        }

        puts("YES");
        res = n % (2 * m);
        if(res != 0) {
            res += 2 * m;
            res = min(n, res);
        }

        //分成2 * m份
        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;
                ans[k].pb(a), ans[k].pb(b);
                sumv[k] += a, sumv[k] += b;
            }
        }

        dis = avg - sumv[1];
        dfs(1, 0, 1);

        for(int i = 1; i <= res; i++) {
            ans[cake[i]].pb(i);
        }

        for(int i = 1; i <= m; i++) {
            int size = ans[i].size();
            printf("%d", size);
            for(int k = 0; k < size; k++) {
                printf(" %d",ans[i][k]);
            }
            puts("");
        }
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-09 08:54:19

hdu 5355 Cake(构造+回溯)的相关文章

HDU 5355 Cake

HDU 5355 Cake 更新后的代码: 今天又一次做这道题的时候想了非常多种思路 最后最终想出了自觉得完美的思路,结果却超时 真的是感觉自己没救了 最后加了记忆化搜索,AC了 好了先说下思路吧.不知道大家住没注意m<=10 我们能够把大部分的数据写成成对的形式比如n=27 m=6的这组数据 第1份  27  16 第2份  26  17 第3份  25  18 第4份  24  19 第5份  23  20 第6份  22  21 剩下1~15搜索出6等份分给全部人 这样成对出现的数蛇形数我

多校第六场 1003 hdu 5355 Cake(贪心)

题目链接:(数据加强后wa了) hdu 5355 题目大意: 给出一个蛋糕.切成1~n大小的n块.问是否能在不继续分割的情况下拼凑出m等份. 题目分析: 首先我们是可以知道每份蛋糕的尺寸的,利用n*(n+1)/2m可以算出来,假设不能整除的话,那么一定无解. 然后我们考虑怎样构造一组解,对于一块蛋糕,我想到了一个贪心策咯,尽量选择最大块的蛋糕,由于假设能选可是不选这块蛋糕,那么也一定是通过选取小块的蛋糕来拼凑出这块蛋糕的大小,可是假设小的拼凑出了这块,那么就不能用于拼凑其它的蛋糕,显然选择最大的

HDU 5355 Cake (WA后AC代码,具体解析,构造题)

题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=5355 题面: Cake Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 1632    Accepted Submission(s): 273 Special Judge Problem Description There are s

HDU 5355 Cake (WA后AC代码,详细解析,构造题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5355 题面: Cake Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 1632    Accepted Submission(s): 273 Special Judge Problem Description There are m

hdu 5535 Cake 构造+记忆化搜索

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5355 题意:给定n与m,其中1<= n <= 1e5,2 <= m <= 10;问是否存在将1~n个数分成m组,使得每组的和相等:若存在输出m行,每行表示一组的值,否则输出NO; ps:总共T<=1000组数据,还是挺大的: 思路:预判之后,若可能存在则直接以2m为周期,从大往小构造出和相等的m组,这样就可以将n的值缩小到2m~4m-2:因为当n = 4m-1时,再次减去一个周期,下

HDU 5355 Cake(2015多校第六场,搜索 + 剪枝)

Cake Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 965    Accepted Submission(s): 119 Special Judge Problem Description There are m soda and today is their birthday. The 1-st soda has prepa

hdu 4850 字符串构造---欧拉回路构造序列 递归+非递归实现

http://acm.hdu.edu.cn/showproblem.php?pid=4850 题意:构造长度为n的字符序列,使得>=4的子串只出现一次 其实最长只能构造出来26^4+4-1= 456979 的序列,大于该数的都是不可能的.构造方法,就是那种欧拉回路的序列,此题DFS会爆栈,手动扩展栈也可以AC...... 递归形式的开始WA了,没有细调就换非递归了,后来又想了想,虽然自己电脑上运行不了,但是先把长度按小的来,然后调试代码,然后在扩大,AC了,当时错在MOD,递归的MOD应该是26

CoderForce 180D-Name (构造+回溯)

题目大意:给两个字符串s,t,用s中的字符重新组合构造出按字典序最小的但比t大的新字符串. 题目分析:先统计s中各个字母出现的次数,然后从t的左端向右端依次构造出新串的每一位上的字母.这个过程我是用回溯实现的,因为只需进行到字典序比t大就可以立即停止,所以实际上花不了多少时间. 代码如下: # include<iostream> # include<string> # include<algorithm> # include<cstdio> # includ

hdu 5339 Untitled(回溯)

hdu 5339 Untitled 题目大意:给出n个数字的序列,和一个数a,在n中有m个数b1,...,bm使得__a %b1%b2%...%bm = 0,求最小的m. 解题思路:回溯. #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <cstdlib> using namespace std; const int N = 5