您的位置:首页 > 大数据 > 人工智能

HDU-- 2015 Multi-University Training Contest 6 Cake

2015-08-06 19:24 435 查看

Cake

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)

Total Submission(s): 0 Accepted Submission(s): 0

Special Judge


[align=left]Problem Description[/align]

There are m soda and today is their birthday. The 1-st soda has prepared n cakes with size 1,2,…,n. Now 1-st soda wants to divide the cakes into m parts so that the total size of each part is equal.

Note that you cannot divide a whole cake into small pieces that is each cake must be complete in the m parts. Each cake must belong to exact one of m parts.


[align=left]Input[/align]

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

The first contains two integers n and m (1≤n≤105,2≤m≤10), the number of cakes and the number of soda.
It is guaranteed that the total number of soda in the input doesn’t exceed 1000000. The number of test cases in the input doesn’t exceed 1000.


[align=left]Output[/align]

For each test case, output "YES" (without the quotes) if it is possible, otherwise output "NO" in the first line.

If it is possible, then output m lines denoting the m parts. The first number si of i-th line is the number of cakes in i-th part. Then si numbers follow denoting the size of cakes in i-th part. If there are multiple solutions, print any of them.


[align=left]Sample Input[/align]

4
1 2
5 3
5 2
9 3


[align=left]Sample Output[/align]

NO
YES
1 5
2 1 4
2 2 3
NO
YES
3 1 5 9
3 2 6 7
3 3 4 8


题意:

n块蛋糕分给m个人,n块蛋糕大小分别为1,。。。n,问是否能平均分配(不能切开任何一块蛋糕)并输出任意一种解

思路:

先求n块蛋糕大小总和sum,判断sum是否是m的倍数且sum/m的值是否能大于或等于n;

如果不满足着两个条件中的任何一个就是“NO”;

若满足,就只要输出结果;

解有很多种,可以用贪心,每次都取一块当前能取的最大的蛋糕,直到不能再取;

最开始写的递归,写完后感觉会T,没敢交,改成循环一次A,又把递归交了一遍,居然过了= =,看来没卡数据。。。

差别就是递归519MS,循环只有15MS。。

//循环:

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 100005
using namespace std;

unsigned long  sum
;
bool number
;//标记蛋糕是否已经取掉
int ans
;
int ret;
int n,m,k = 0;
int ncount = 0;

void ini( int x)//计算x个蛋糕到小总和
{
if(sum[x] == 0)
{
sum[x] = ((x + 1) * x)  >> 1;
}
}

void Find(int x)//查找平均大小为x的分配方案
{
int i,j,k;
int temp;
for(i = 0; i < m; i++)
{
temp = x;
j = n;
for(j = n;j > 0;j--)
{
if((temp - j >= 0) && number[j] == 0)//每次取能取的最大蛋糕
{
ans[ncount++] = j;
number[j] = 1;
temp -= j;
}
if(temp == 0) break;
}
printf("%d ",ncount);
for(k = 0; k < ncount; k++)
{
printf("%d ",ans[k]);
}
printf("\n");
ncount = 0;
}
}

int main()
{
int i,j;
int T;

//freopen("FileIn.txt","r",stdin);
//freopen("FileOut.txt","w",stdout);

scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
ini(n);
memset(number,0,sizeof(number));//初始化标记方阵
if(sum
% m == 0 && sum
/ m >= n)
{
printf("YES\n");
ret = sum
/ m;
Find(ret);
}
else
{
printf("NO\n");
}
}

//fclose(stdin);
//fclose(stdout);

return 0;
}

//递归算法:
//(这个递归有点乱,有点像DFS)
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 100005
using namespace std;

unsigned long  sum
;
bool number
;
int ans
;
int ret;
int n,m,k = 0;
int ncount = 0;

void ini( int x)
{
if(sum[x] == 0)
{
sum[x] = ((x + 1) * x)  >> 1;
}
}

void Find(int x)
{
int i,j;
if(x == 0)
{
printf("%d ",ncount);
for(i = 0; i < ncount; i++)
{
printf("%d ",ans[i]);
}
printf("\n");
ncount = 0;
Find(ret);
return;
}
for(i = n; i > 0; i--)
{
if(x - i>= 0 && number[i] == 0)
{
ans[ncount++] = i;
number[i] = 1;
Find(x - i);
}
}

}

int main()
{
int i,j;
int T;

//freopen("FileIn.txt","r",stdin);
//freopen("FileOut.txt","w",stdout);

scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
ini(n);
memset(number,0,sizeof(number));
if(sum
% m == 0 && sum
/ m >= n)
{
printf("YES\n");
ret = sum
/ m;
Find(ret);
}
else
{
printf("NO\n");
}
}

//fclose(stdin);
//fclose(stdout);

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