AtCoder Beginner Contest 123 D

题目链接

题目大意:

给出a,b,c三个数组,数组长度分别为x,y,z(1<=x,y,z<=1000),从这三个数组各挑选一个元素相加可以有x*y*z种可能,现在让你输出前k(k<=min(3000,x*y*z))个大的情况。

分析:

如果不给出限制的话,就直接遍历一遍,但是x*y*z现在明显是会超时的,但是k是小于3000的,所以这道题的解决方法是广搜。首先,确定起点,那么必定是三个数组最大的相加,那么应该怎么走呢?明显的,题目要求从大到小输出,比起点小的有哪些情况,有三种,第一种a的第二大+b的第一大+c的第一大,第二种a的第一大+b的第二大+c的第一大,第三种a的第一大+b的第一大+c的第二大,想到了这三种情况,那么路径就已经规划好了,但到底该选哪条呢?这里就要用到优先队列,每次选择最大的就可以了。

代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
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.wq;
ll a[N],b[N],c[N];
int k;
mapmmp;
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

 

你可能感兴趣的:(Atcoder,BFS)