Problem Description
Davy Jones has captured another ship and is smiling contently under the sun. Today is a good day for him. He will get more souls to serve on his crew. The day, however, looks so nice, the sun shining brightly above all and the ocean spilled calmly around, that he decides to be merciful and give some
chance to the wretched seamen of the captured ship. He decides to play the following game.
He will line a group of captives in front of him, and then write a number of his choice on each
man’s forehead. After that, he wants to check if the set of numbers is 3-free. What does it mean for a set to be 3-free? It means that there are no 3 numbers in the set that form an increasing arithmetic progression (weird games have damned Jones, aye), i.e., a sequence of numbers such that the difference of any two successive members of the sequence is a positive constant, such as {1 2 3}, {4 6 8}, or {-2, 1, 4}. If the the set of numbers on men’s foreheads is 3-free, the group is free, too (what an irony).
However, if not, those who have the numbers of the lexicographically first triple that proves (i.e. is a witness) that the set is not 3-free will serve on Jones’ crew for an eternity.
And you ... You will be Jones’ assistant in this game. Checking each group whether it is 3-free or not. And you’d better check right or you will end up on Jones’ crew as well.
A triple (a1, a2, a3) is an increasing arithmetic progression if a2-a1=a3-a2, and a2-a1>0.
A triple (a1, a2, a3) is lexicographically smaller than (b1, b2, b3) if
a1 < b1, or
a1 = b1 and a2 < b2, or
a1 = b1, a2 = b2 and a3 < b3.
Note that you will be looking at triples (a1, a2, a3) of increasing order, i.e. a1 ≤ a2 ≤ a3. The numbers on men’s foreheads need not be in increasing order though.
Input
Input consists of a single line with the numbers written on the captured men’s foreheads. The first number of the line denotes how many men are there in the group(it will not exceed 10000) and should not be included in the sequence.
Output
Output should consist of a single line. If the sequence of numbers in the input is 3-free, output “Sequence is 3-free.” If the sequence is not 3-free, output “Sequence is not 3-free. Witness: w1, w2, w2.” (note the intervals after the first dot and the colon), where w1, w2, w3 is the lexicographically first witness that the sequence is not 3-free.
Sample Input`
4 1 5 6 8
7 1 3 5 2 -7 0 -1`
Sample Output`
Sequence is 3-free.
Sequence is not 3-free. Witness: -7,-1,5.`
题目分析:
要求给出的一组数据中任意的三个数不能构成"3-free"(即三个数不能够是公差大于零的等差数列),为了方便查找我们可以先把给出的这组数据按照升序排列,然后循环找出首项和末项,再判断他们的中间项是不是在这组数据中。
找中间项时如果还用for循环查找的话,相当于三层for循环嵌套,所需要的运行时间太大,可以用set容器或则map容器优化这个查找过程。
三层for循环嵌套(超时)
#include<iostream>
#include<stdio.h>
#include<set>
#include<algorithm>
using namespace std;
int a[10009];
int main()
{
int n,i,j;
while(~scanf("%d",&n))
{
for(i=0; i<n; i++)
{
scanf("%d",&a[i]);
}
sort(&a[0],&a[n]);//因为要看能否构成等差数列我们
//先给数据排序这样方便后面的比较
int op=0; //op作为一个标记,看看后面是否满足条件的
for(i=0; i<n; i++)
{
for(j=i+2; j<n; j++)
{
int m,bj=0;
m=(a[i]+a[j])/2;
for(int k=0; k<n-1; k++) // 因为多加了一个找中间值的循环,运行时间会超限
{
if(a[k]==m)
{
bj=1;
break;
}
}
if(bj==1)
{
if((a[i]+a[j])%2==0)//保证中间的那个数是满足条件的整数
{
op=1;
printf("Sequence is not 3-free. Witness: %d,%d,%d.\n",a[i],(a[i]+a[j])/2,a[j]);
break;
}
}
}
if(op==1)break;
}
if(op==0)
printf("Sequence is 3-free.\n");
}
return 0;
}
set容器优化
#include<iostream>
#include<stdio.h>
#include<set>
#include<algorithm>
using namespace std;
int a[10009];
int main()
{
int n,i,j;
set<int>s;
while(~scanf("%d",&n))
{
for(i=0; i<n; i++)
{
scanf("%d",&a[i]);
s.insert(a[i]);
}
sort(&a[0],&a[n]);
int op=0;
for(i=0; i<n; i++)
{
for(j=i+2; j<n; j++)
{
if((a[i]+a[j])%2==0&&s.find((a[i]+a[j])/2)!=s.end())//保证中间的那个数是满足条件的整数,
//且存在于输入的数据中
{
op=1;
printf("Sequence is not 3-free. Witness: %d,%d,%d.\n",a[i],(a[i]+a[j])/2,a[j]);
break;
}
}
if(op==1)break;
}
if(op==0)
printf("Sequence is 3-free.\n");
}
return 0;
}
map容器优化
#include<iostream>
#include<stdio.h>
#include<map>
#include<algorithm>
using namespace std;
int a[10009];
int main()
{
int n,i,j;
while(~scanf("%d",&n))
{
map<int,int>m;
for(i=0; i<n; i++)
{
scanf("%d",&a[i]);
m[a[i]]=1;
}
sort(&a[0],&a[n]);
int op=0; //op作为一个标记,看看后面是否满足条件的
for(i=0; i<n; i++)
{
for(j=i+2; j<n; j++)
{
if((a[j]+a[i])%2==0&&m[(a[j]+a[i])/2]==1)//保证中间的那个数存在
{
op=1;
printf("Sequence is not 3-free. Witness: %d,%d,%d.\n",a[i],(a[i]+a[j])/2,a[j]);
break;
}
}
if(op==1)break;
}
if(op==0)
printf("Sequence is 3-free.\n");
}
return 0;
}