zoukankan      html  css  js  c++  java
  • 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
    ");
        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("
    ");
        }
    }
    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
    ");
            else{
                Init();
                bool ok=fun(n);
                if(ok)out(m);
                else printf("NO
    ");
            }
        }
        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
    ");
                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
    ");
                        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("
    ");
                        }
                    }
                    else
                        printf("NO
    ");
                }
            }
            else
                printf("NO
    ");
        }
        return 0;
    }


  • 相关阅读:
    韩寒首度回应小三事件:望女友妻子和平相处_陕西频道_凤凰网
    冒泡排序 oj Google 搜索
    on call是什么意思_on call的翻译_音标_读音_用法_例句 必应 Bing 词典
    分享:创业失败后如何找工作
    美国出台高科技人才移民优惠政策_the United States 美国_cnBeta.COM
    分别用数组和链表实现堆栈(C语言版) ahljjun的专栏 博客频道 CSDN.NET
    分享:void及void指针深层次探索
    浅谈基础算法之堆栈(五) 川山甲 博客园
    分享:【原创】Stringification 在二级宏定义中的使用
    System Engineer / Backend Engineer
  • 原文地址:https://www.cnblogs.com/gccbuaa/p/7094860.html
Copyright © 2011-2022 走看看