Quantcast
Channel: CSDN博客推荐文章
Viewing all articles
Browse latest Browse all 35570

ZOJ 1101 Gamblers

$
0
0

本来想做dp题的,上网找分类,偶然看到这道题,据说无数人WA。。

上去一看3000/15000

在长度为1000的序列中找到w,x,y,z,使得a[w]+a[x]+a[y]=a[z]

其中序列元素互不相同,数值范围-1<<29到1<<29

A了以后证实不用long和long long

一般网上的解法都是n^3枚举+log(n)二分

对于1<=n<=1000来说太吓人了。。。

想了很久,想到先预处理n*n个sum=a[w]+a[x],然后枚举a[z]和a[y],二分找sum,

预处理的时候需要记录对于某个sum,需要记录得到它的a[w]和a[x],这样避免枚举到sum+a[y]=a[z],其中sum是由a[y]或者a[z]得到的。

我目测时间复杂度是n^2log(n^2),但是在和ac代码对拍的时候发现明显比n^3log(n)慢得多,,不知道为什么,求大牛指教。

代码:

#define X 1010
#include<stdio.h>
#include<algorithm>
using namespace std;
struct Sum{
	int a,b,c;
}sum[X*X];
bool cmp(Sum x,Sum y){
	if(x.c!=y.c)return x.c<y.c;
	if(x.a!=y.a)return x.a<y.a;
	if(x.b!=y.b)return x.b<y.b;
}
int bi(int x,int r){
	int l=0,m;
	while(l<r){
		m=l+r>>1;
		if(sum[m].c<x)l=m+1;
		else      r=m;
	}
	return r;
}
int a[X];
int main(){
//	freopen("in.txt","r",stdin);
//	freopen("out.txt","w",stdout);
	int i,j,n,m,k,top;
	while(scanf("%d",&n),n){
		for(i=0;i<n;i++)
		    scanf("%d",&a[i]);
		if(n<4){puts("no solution");continue;}
        sort(a,a+n);
		for(i=top=0;i<n;i++)
		  for(j=i+1;j<n;j++){
			sum[top].a=a[i];
			sum[top].b=a[j];
			sum[top].c=a[i]+a[j];
			top++;
		}
		sort(sum,sum+top,cmp);
		k=X;
		for(i=n-1;i>=0;i--)
		    for(j=n-1;j>=0;j--)
			if(i!=j){
				m=bi(a[i]-a[j],top);
				while(sum[m].c==a[i]-a[j]){
					if(sum[m].a!=a[j]&&sum[m].b!=a[j]
					 &&sum[m].a!=a[i]&&sum[m].b!=a[i])
					    {k=i;break;}
					m++;
				}
				if(k==i)i=j=-9;
			}
		if(i==-10)printf("%d\n",a[k]);
		else      puts("no solution");
	}
	return 0;
}


别人的代码很明显for(i=0;i<n;i++)for(j=0;j<n;j++)for(k=0;k<n;k++)lower_bound()

我的代码很明显for(i=0;i<n;i++)for(j=0;j<n;j++)lower_bound()

其中while循环可以证明最多循环3次

因为对于固定的sum 只可能sum.a==a[i]或者sum.a==a[j]

实在找不出为什么慢了。。。

作者:zzxyyx_1 发表于2013-1-15 21:39:18 原文链接
阅读:22 评论:0 查看评论

Viewing all articles
Browse latest Browse all 35570

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>