https://www.51nod.com/Challenge/Problem.html#problemId=1267
第一种方法:两个for+二分:很好理解,不用考虑重复的问题。但是这个还不够快
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e3+10;
ll a[maxn];
int main()
{
ll n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
int ok=0;
sort(a,a+n);
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
ll sum;
ll k=j+1,m=n-1;
while(k<m)
{
sum=a[i]+a[j]+a[k]+a[m];
if(sum<0)
{
k++;
}
else if(sum>0)
{
m--;
}
else
{
ok=1;break;
}
}
if(ok)
break;
}
if(ok)
break;
}
if(ok)
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
第二种,尺取法,复杂度为n,我们把所有两两相加存起来,再进行二分,但是二分时要加一个判断防止出现重复,这里结构体记录的是坐标与和
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 1e3+5;
int a[maxn];
int n;
struct node
{
int x,y,s;
}st[maxn*maxn];
bool cmp(node a,node b)
{
return a.s<b.s;
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
int tot=0;
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
st[tot].s=a[i]+a[j];
st[tot].x=i;
st[tot].y=j;
tot++;
}
}
sort(st,st+tot,cmp);
int l=0,r=tot-1;
int ok=0;
while(l<r)
{
if(st[l].s+st[r].s==0)
{
if(st[l].x!=st[r].x&&st[l].x!=st[r].y&&
st[l].y!=st[r].y&&st[l].y!=st[r].x)
{
ok=1;break;
}
else
l++,r--;
}
else if(st[l].s+st[r].s>0)
r--;
else
l++;
}
if(ok)
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
这个写了好几遍因为一直判我超时,上面的过了,但是我还有个跟它一样的代码(至少经检查是一样的)交了无数遍都不过,至今未解。