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等份分给全部人

这样成对出现的数蛇形数我们去处尽量多的偶数条

保证剩下的数的个数大于等于2*m小于4*m个

所以剩下的小于4m(小于40)个数我们仅仅解用搜索就好了

所以n 的范围就变成1~40,m的范围1~10这样我们记录这些的结果(防止这种数据大量反复出现)

这样假设我们有数据15 6计算过后

n=27  m= 6

n=39  m=6

n=15+(随意被的12) m=6

我们都不须要搜索了

就这样这个问题就攻克了

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#define maxn 100005
#define ll __int64
#define cnm c[nu][m]
using namespace std;
int v[15][maxn];
ll m,n;
//fun函数定义将1-num平均分给l-r个人
int a[15][50];
int si[15];
bool b[50];
int dp[50][10]={0};
int c[50][10][15][50]={0};
ll ave,nu;
bool dfs(int sum,int g,int s){
    if(sum==ave){g++;sum=0;s=1;}
    if(g==m-1){
        for(int i=1;i<=nu;i++)
            if(!b[i])a[g][++a[g][0]]=i;
        return true;
    }
    for(int i=s;i<=nu;i++){
        if(sum+i>ave) return false;
        if(!b[i]){
            b[i]=true;
            a[g][++a[g][0]]=i;
            if(dfs(sum+i,g,i+1)) return true;
            b[i]=false;
            a[g][0]--;
        }
    }
    return false;
}

bool fun(ll num){
    if(num>=4*m-1){
        for(int i=0,j=0;i<m;i++,j++){
            v[i][si[i]++]=num-j;
            v[i][si[i]++]=num-2*m+1+j;
        }
        return fun(num-2*m);
    }
    else {
        nu=num;
        ave=(num+1)*num/2/m;
        int b;
        if(dp[num][m]==0){
            if(dfs(0,0,1)){
                dp[num][m]=1;
                for(int i=0;i<m;i++)
                    for(int j=0;j<=a[i][0];j++)
                        cnm[i][j]=a[i][j];
            }
            else dp[num][m]=-1;
        }
        if(dp[nu][m]==1) return true;
        return false;
    }
}
void out(int n){
    printf("YES\n");
    for(int i=0;i<n;i++){
        printf("%d",si[i]+cnm[i][0]);
        for(int j=0;j<si[i];j++) printf(" %d",v[i][j]);
        for(int j=0;j<cnm[i][0];j++) printf(" %d",cnm[i][j+1]);
        printf("\n");
    }
}
void Init(){
    memset(si,0,sizeof(si));
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%I64d%I64d",&n,&m);
        ll su=n*(n+1)/2;
        ll av=su/m;
        if(su%m||av<n)printf("NO\n");
        else{
            Init();
            bool ok=fun(n);
            if(ok)out(m);
            else printf("NO\n");
        }
    }
    return 0;
}

/*

此代码存在局限性数据更新后已不能在AC

待更新……

*/

这个题目看上去的时候第一感觉就是暴力,结果真的一遍就过了

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#define maxn 100005
#define ll __int64
using namespace std;
int a[maxn];
vector <int > v[maxn];
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        ll n,m;
        scanf("%I64d%I64d",&n,&m);
        ll sum =(n+1)*n/2;
        if(sum%m==0){
            ll ave=sum/m;
            if(ave<n)
                printf("NO\n");
            else{
                memset(v,0,sizeof(v));
                memset(a,0,sizeof(a));
                int t=ave,A=0;
                int flag=0;
                for(int i=n;!flag&&i>=1;i--){
                    if(a[i]==0){
                        t-=i;
                        v[A].push_back(i);
                        a[i]=1;
                    }
                    if(i-1>t){
                        for(int j=i-1;t&&j>=1;j--){
                            if(t>=j&&a[j]==0){
                                v[A].push_back(j);
                                t-=j;
                                a[j]=1;
                            }
                        }
                    }
                    if(t==0){
                        t=ave;
                        A++;
                    }
                }
                if(A==m){
                    printf("YES\n");
                    for(int i=0;i<m;i++){
                        printf("%d",v[i].size());
                        for(int j=0;j<v[i].size();j++)
                            printf(" %d",v[i][j]);
                        printf("\n");
                    }
                }
                else
                    printf("NO\n");
            }
        }
        else
            printf("NO\n");
    }
    return 0;
}
时间: 2024-10-11 03:33:42

HDU 5355 Cake的相关文章

多校第六场 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 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 5355 Cake(构造+回溯)

题意: 给出一个蛋糕,切成1~n大小的n块,问能否在不继续切割的情况下拼凑出m等份. 解析: 首先可以求出这些蛋糕的总和n?(n+1)/2,如果总和sum%m != 0那么就不肯能被平分成m份,那么输出"NO". 接下来计算平均数avg=sum/m,如果平均数avg < n的话,蛋糕是不可能用完的,同样也输出"NO". 剩下的情况蛋糕是一定能拼成"YES"的,那么可以将这些蛋糕以2*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 1722 Cake 数学yy

题链:http://acm.hdu.edu.cn/showproblem.php?pid=1722 Cake Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2620    Accepted Submission(s): 1364 Problem Description 一次生日Party可能有p人或者q人参加,现准备有一个大蛋糕.问最

hdoj 5355 Cake(分析+二分)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5355 分蛋糕的题目,有1-n大小的n个蛋糕,要求平均分成m份,不能切开蛋糕 1 #include<stdio.h> 2 #include<set> 3 using namespace std; 4 int main(){ 5 set<int>s; 6 set<int>::iterator it; 7 long long n; 8 int m; 9 int par

HDU 1722 Cake

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1722 一块蛋糕切成多少块,才能使无论是来 q 个人还是 p 个人都能均分 P 个人 --> P 块 Q 个人 --> Q 块 块数最少,则减去 P Q 切法 中重合的部分 g.c.d.(p,q) #include<bits/stdc++.h> int main() { int p, q; while (~scanf ("%d%d", &p, &q)