喜欢acm,因为有挑战,很纯粹,付出了便会有收获。
题意:有a个1,b个2,c个3,d个4,问能否不重不漏的划分成一些长度大于等于3的等差数列(一个数列可以
出现多次)?
今天开始训练用科学的方法来解题:
首先注意到这是一个对称的数列,a,b,c,d,所以可以分类从两方面着手问题:1.从两边开始着手,2.从中间着手。
注意到如果想满足成立的条件必须要把使b == c,而两边着手问题没有太多的条件可以使用。
所以,我们从中间开始思考,首先发现必须使b == c && max(a,d) <= b && b <= a + d,如果能达到上述条件就能
将所有元素不重不漏的拿光(极限情况,如果b == a + d,使a,b,c 和 b,c,d分别为等差数列,如果a == b == c == d
则a,b,c,d为等差数列)。
所以核心思路就是先枚举中间的情况,再枚举两边的情况,再注意边界处理便可以了
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define check(i) (i != 1 && i != 2)
#define done(a,b,c,d) (b == c && max(a,d) <= b && b <= a + d)
inline bool _check_(int a,int b,int c,int d)
{
for(int i = max(a - b,0);i <= a && (a - i) + d >= b;i++)
for(int j = d - b;j <= d && (a - i) + (d - j) >= b;j++)
if(check(i) && check(j) && done(a - i,b,c,d - j))
return true;
return false;
}
inline bool run(int a,int b,int c,int d)
{
if(done(a,b,c,d))return true;
if(a > 2 && b > 2 && c > 2 && d > 2)return true;
if(b > c)swap(b,c);
if(a > d)swap(a,d);
for(int i = max(b - (a + d),0);i <= b;i++)
if(check(i) && check(c - b + i))
if(done(a,b - i,b - i,d) || _check_(a,b - i,b - i,d))
return true;
return false;
}
int main()
{
int _,a,b,c,d;
scanf("%d",&_);
while(_--)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
bool ans = run(a,b,c,d);
if(ans)puts("Yes");
else puts("No");
}
}
看到bestCoder提供了另一种方法比较容易编写
如果把所有形如123,123,123看成是三个常数列111,222,333。那么123,234,1234,各自出现的情况只能是0,1,2次
对123,234,1234出现的次数进行枚举,剩下的均当作常数列验证是否可行
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define FOR(i) for(int i = 0;i <= 2;i++)
#define test(i) (i != 1 && i != 2 && i >= 0)
#define MAXN 30
int cnt = 0;
struct Node
{
int a,b,c,d;
}node[MAXN];
void run()
{
FOR(i)FOR(j)FOR(k)
{
node[cnt].a = i + j;
node[cnt].b = i + j + k;
node[cnt].c = i + j + k;
node[cnt++].d = i + k;
}
}
bool check(int a,int b,int c,int d)
{
for(int i = 0;i < cnt;i++)
if(test(a - node[i].a) && test(b - node[i].b) && test(c - node[i].c) && test(d - node[i].d))
return true;
return false;
}
int main()
{
int _,a,b,c,d;
run();
scanf("%d",&_);
while(_--)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
bool ans = check(a,b,c,d);
if(ans)puts("Yes");
else puts("No");
}
}