HDU 5355 Cake

来源:互联网 发布:清洁pcb的玻璃笔淘宝 编辑:程序博客网 时间:2024/06/03 18:08

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 __int64using 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;}


0 0
原创粉丝点击