您的位置:首页 > 其它

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

我们都不需要搜索了

就这样这个问题就解决了

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: