题目连接ios
题目大意:数组
给出a,b,c三个数组,数组长度分别为x,y,z(1<=x,y,z<=1000),从这三个数组各挑选一个元素相加能够有x*y*z种可能,如今让你输出前k(k<=min(3000,x*y*z))个大的状况。spa
分析:code
若是不给出限制的话,就直接遍历一遍,可是x*y*z如今明显是会超时的,可是k是小于3000的,因此这道题的解决方法是广搜。首先,肯定起点,那么一定是三个数组最大的相加,那么应该怎么走呢?明显的,题目要求从大到小输出,比起点小的有哪些状况,有三种,第一种a的第二大+b的第一大+c的第一大,第二种a的第一大+b的第二大+c的第一大,第三种a的第一大+b的第一大+c的第二大,想到了这三种状况,那么路径就已经规划好了,但到底该选哪条呢?这里就要用到优先队列,每次选择最大的就能够了。队列
代码:get
#include<cstdio> #include<cstdlib> #include<cstring> #include<queue> #include<cmath> #include<map> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int N=1000+5,dx[]={0,0,1},dy[]={0,1,0},dz[]={1,0,0}; bool cmp(ll x,ll y)//从大到小 { return x>y; } struct P{ int x,y,z; ll w; P(){}; P(int a,int b,int c,ll ww) { x=a;y=b;z=c;w=ww; } friend bool operator<(const P &p1,const P &p2)//从大到小 { return p1.w<p2.w; } }; priority_queue<P>q; ll a[N],b[N],c[N]; int k; map<ll,int>mmp; ll zh(int x,int y,int z)//将x,y,z转换成一个长整型,用来映射 { return x*100000000+y*10000+z; } int x,y,z; void bfs() { mmp[0]=1; q.push(P(0,0,0,a[0]+b[0]+c[0])); while(!q.empty()&&k) { P p=q.top(); q.pop(); k--; printf("%lld\n",p.w); for(int i=0;i<3;i++) { int nx=p.x+dx[i],ny=p.y+dy[i],nz=p.z+dz[i]; if(nx<x&&ny<y&&nz<z&&!mmp[zh(nx,ny,nz)]) { mmp[zh(nx,ny,nz)]=1; q.push(P(nx,ny,nz,a[nx]+b[ny]+c[nz])); } } } while(!q.empty()){ q.pop(); } } int main() { scanf("%d%d%d%d",&x,&y,&z,&k); for(int i=0;i<x;i++) { scanf("%lld",&a[i]); } for(int i=0;i<y;i++) { scanf("%lld",&b[i]); } for(int i=0;i<z;i++) { scanf("%lld",&c[i]); } sort(a,a+x,cmp); sort(b,b+y,cmp); sort(c,c+z,cmp); bfs(); return 0; }