Tempter of the Bone
Cake
今天又出去玩了,没完成,,
Tempter of the Bone
题目大意、剪枝思想看上一篇文章
这个题错的原因是:
1.没想明白总时间和剩余时间的区别
2.continue达成break
我是傻逼
Cake
Problem Description
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.
Input
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.
Output
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.
Sample Input
4
1 2
5 3
5 2
9 3
Sample Output
NO
YES
1 5
2 1 4
2 2 3
NO
YES
3 1 5 9
3 2 6 7
3 3 4 8
题目大意这个就是把1、2、3……n分成m组,使得每组总和相等。
这个题选取顺序就很重要了。要优先选取大的。
记得昨天的题吗?(还是前天)我问题出错在这一组先选取这个可能导致另一组无法凑齐,今天相出了解决方法。就是先选取大的,因为造成上述后果的原因无非是能拿一个整块的,却拿了几个小的。
比如我还差5,这时我可以拿5,可以拿1和4.如果我拿了1和4就可能导致后面的无法凑齐。如果我优先选取大的就没这些顾虑了。直接m-1次选取即可 。
做这个题的时候爆栈了。解决方法一就是上述,循环m-1次。另外一个方法就是用老师的代码方法,用一个循环选取当前数字之后的数字。这时如果不选取就不会有一个栈了。应该能减少不小的空间。
代码如下
//You has the final say in what kind of life you want.
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#define MAX 100000+10
using namespace std;
int n,m;
bool vis[MAX];
vector<int>ans[20];
bool devide(int x,int s,int cur,int now)
{
if(now==x)
{
// for(int i=1;i<=n;i++)
// if(!vis[i])
// ans[s].push_back(i);
return 1;
}
if(cur<=0)return 0;
if(!vis[cur]&&now+cur<=x)
{
vis[cur]=1;
if(devide(x,s,cur-1,now+cur))
{
ans[s].push_back(cur);
return 1;
}
vis[cur]=0;
}
long long temp=(long long)(cur)*(cur-1)/2;
if(now+temp>=x)
if(devide(x,s,cur-1,now))
return 1;
return 0;
}
bool check(int x)
{
for(int i=0;i<m;i++)
{
if(!devide(x,i,n,0))
return 0;
}
for(int i=1;i<=n;i++)
if(!vis[i])
ans[3].push_back(i);
return 1;
}
int main()
{
int T;
long long temp;
cin>>T;
while(T--)
{
for(int i=0;i<20;i++)
ans[i].clear();
memset(vis,0,sizeof(vis));
scanf("%d%d",&n,&m);
temp=(long long)(1+n)*n/2;
if(temp%m||temp/m<n)
{
printf("NO\n");
continue;
}
if(check(temp/m))
{
printf("YES\n");
for(int i=0;i<m;i++)
{
printf("%d ",ans[i].size());
// for(int j=ans[i].size()-1;j>=0;j--)
for(int j=0;j<ans[i].size();j++)
printf("%d ",ans[i][j]);
printf("\n");
}
}
else printf("NO\n");
}
return 0;
}
最近快结束了,很浮躁。还有很长的路要走,别松懈啊。