HDU 4334 && ZOJ 3631

来源:互联网 发布:thinsulate 知乎 编辑:程序博客网 时间:2024/05/06 11:54

都是用到了求分别在两个数组中的两个数使之和满足某个条件

方法是先排序,然后用两个指针 i,j 分别指向两个数组的头和尾,再调整移动指针。

zoj 3631

#include <cstdio>#include <cstring>#include <cstdlib>#include <vector>#include <algorithm>using namespace std;int main(){    int i,j,a[50],ans,n,m;    int sum1[40000],sum2[40000];    //freopen("a.txt","r",stdin);    //freopen("b.txt","w",stdout);    while(scanf("%d %d",&n,&m)==2){        for(i=1;i<=n;i++)            scanf("%d",&a[i]);        memset(sum1,0,sizeof(sum1));        memset(sum2,0,sizeof(sum2));        for(i=0;i<=(1<<(n/2))-1;i++)            for(j=1;j<=n/2;j++)                if(i&(1<<(j-1)))                    sum1[i]+=a[j];        int p=n-n/2;        for(i=0;i<=(1<<p)-1;i++)            for(j=1;j<=p;j++)                if(i&(1<<(j-1)))                    sum2[i]+=a[j+n/2];        sort(sum1,sum1+(1<<(n/2)));        sort(sum2,sum2+(1<<p));        ans=0;        for(i=0,j=(1<<p)-1;i<(1<<(n/2))&&j>=0;)            if(sum1[i]+sum2[j]<=m){                ans=max(ans,sum1[i]+sum2[j]);                i++;            }            else                j--;        printf("%d\n",ans);    }}

hdu 4334

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;__int64 a[10][201],sum2[50010],sum1[50010];int main(){    int t,T,i,j,n,k1,k2,flag,kk,p,q;    __int64 tem;    scanf("%d",&T);    for(t=1;t<=T;t++){        scanf("%d",&n);        for(i=1;i<=5;i++){            for(j=1;j<=n;j++)                scanf("%I64d",&a[i][j]);        }        sort(a[5]+1,a[5]+1+n);        kk=0;        for(i=1;i<=n;i++)            for(j=1;j<=n;j++)                sum1[kk++]=a[1][i]+a[2][j];        sort(sum1,sum1+kk);        k1=unique(sum1,sum1+kk)-sum1;        kk=0;        for(i=1;i<=n;i++)            for(j=1;j<=n;j++)                sum2[kk++]=a[3][i]+a[4][j];        sort(sum2,sum2+kk);        k2=unique(sum2,sum2+kk)-sum2;        flag=0;        for(i=1;i<=n&& !flag;i++){            for(p=0,q=k2-1;p<k1 && q>=0;){                if(sum1[p]+sum2[q]+a[5][i]==0){                    flag=1;                    break;                }                else if(sum1[p]+sum2[q]+a[5][i]>=0)                    q--;                else                    p++;            }        }        if(flag==1)            printf("Yes\n");        else            printf("No\n");    }}

hdu 4334 也可hash

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef __int64 int64;#define inf 100007int64 a[10][201],sum1[50010];//int head[100010],cnt;struct point{    int64 real;//    int next;}edge[50010];void add(int64 tem){  //    int64 hash=tem%inf;   //                   先取余  !!!!!!!!    if(hash<0)        hash+=inf;        for(int i=head[hash];i!=-1;i=edge[i].next){        if(tem==edge[i].real)            return;    }    edge[cnt].real=tem;    edge[cnt].next=head[hash];    head[hash]=cnt++;}int query(int64 tem){    int64 hash=(-tem)%inf;    if(hash<0)        hash+=inf;    for(int i=head[hash];i!=-1;i=edge[i].next){        if((-tem)==edge[i].real){            return 1;        }    }    return 0;}int main(){    int t,T,i,j,k,n,k1,flag,kk;    scanf("%d",&T);    for(t=1;t<=T;t++){        memset(head,-1,sizeof(head));        cnt=0;        scanf("%d",&n);        for(i=1;i<=5;i++){            for(j=1;j<=n;j++)                scanf("%I64d",&a[i][j]);//        }        kk=0;        for(i=1;i<=n;i++)            for(j=1;j<=n;j++)                add(a[1][i]+a[2][j]);        flag=0;        for(i=1;i<n && !flag;i++)            for(j=1;j<=n && !flag;j++)                for(k=1;k<=n && !flag;k++)                    if(query(a[3][i]+a[4][j]+a[5][k])){                        flag=1;                        break;                    }        if(flag==1)            printf("Yes\n");        else            printf("No\n");    }}