HDU 5355 Cake
2015-08-06 17:34
381 查看
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
我们都不需要搜索了
就这样这个问题就解决了
/*
此代码存在局限性数据更新后已不能在AC
待更新……
*/
这个题目看上去的时候第一感觉就是暴力,结果真的一遍就过了
更新后的代码:
今天重新做这道题的时候想了很多种思路
最后终于想出了自认为完美的思路,结果却超时
真的是感觉自己没救了
最后加了记忆化搜索,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; }
相关文章推荐
- bzoj 1030
- Xamarin安装和跳坑指南
- iOS 导航栏返回按钮时间action获取
- Java程序设计之算出一年第多少天
- bzoj 1030 分类: bzoj templates 2015-08-06 17:34 10人阅读 评论(0) 收藏
- 【Thinking in Java】编写构造器时应注意:尽量避免调用其他非private方法
- VB-控件注册 - 利用资源文件将dll、ocx打包进exe文件
- 短信验证
- 浏览器 猛犸
- 公用方法Store
- pickle模块的基本使用
- 工具资源网站
- poj-1094 Sorting It All Out
- Android 图片内存溢出处理笔记
- Android 蓝牙设备的开启与关闭功能的实现
- android优化工具
- Redis集群主备模式部署
- 深入理解C语言(转载)
- POJ 1236 Network of Schools(强连通分量缩点求根节点和叶子节点的个数)
- android:showAsAction="always|withText"分析