Submission #536880

#TimeUsernameProblemLanguageResultExecution timeMemory
53688079brueSoccer (JOI17_soccer)C++14
35 / 100
3052 ms168356 KiB
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

struct dat{
    ll x, y, d; int i;
    dat(){}
    dat(ll x, ll y, ll d, int i): x(x), y(y), d(d), i(i){}
};

struct cont{
    ll x, y; int d, i; ll dist;
    cont(){}
    cont(ll x, ll y, int d, int i, ll dist): x(x), y(y), d(d), i(i), dist(dist){}

    bool operator<(const cont &r)const{
        return dist > r.dist;
    }
};

const int xx[]={0, 1, 0, -1}, yy[]={1, 0, -1, 0};

int n, m, k;
ll a, b, c;
ll x[100002], y[100002];
ll near[502][502][2];
int nearIdx[502][502][2];
ll dist[502][502][5][2];
int distIdx[502][502][5][2];
ll ans = LLONG_MAX;

void makeNear(){
    for(int i=0; i<=n; i++){
        for(int j=0; j<=m; j++){
            near[i][j][0] = near[i][j][1] = 1e18;
            nearIdx[i][j][0] = nearIdx[i][j][1] = -1;
            for(int dir=0; dir<5; dir++){
                dist[i][j][dir][0] = dist[i][j][dir][1] = 1e18;
                distIdx[i][j][dir][0] = distIdx[i][j][dir][1] = -1;
            }
        }
    }

    queue<dat> que;
    for(int i=1; i<=k; i++){
        que.push(dat(x[i], y[i], 0, i));
        for(int j=0; j<2; j++){
            if(near[x[i]][y[i]][j] == 1e18){
                near[x[i]][y[i]][j] = 0;
                nearIdx[x[i]][y[i]][j] = i;
                break;
            }
        }
    }

    while(!que.empty()){
        dat tmp = que.front();
        que.pop();

        for(int d=0; d<4; d++){
            int tx = tmp.x+xx[d], ty = tmp.y+yy[d];
            if(!(0<=tx&&tx<=n&&0<=ty&&ty<=m) || nearIdx[tx][ty][1] != -1 || nearIdx[tx][ty][0] == tmp.i) continue;
            int u = 0;
            if(nearIdx[tx][ty][0] != -1) u=1;
            near[tx][ty][u] = tmp.d + 1;
            nearIdx[tx][ty][u] = tmp.i;
            que.push(dat(tx, ty, tmp.d+1, tmp.i));
        }
    }
}

int main(){
    scanf("%d %d %lld %lld %lld %d", &n, &m, &a, &b, &c, &k);
    for(int i=1; i<=k; i++) scanf("%lld %lld", &x[i], &y[i]);
    makeNear();

    for(int i=0; i<=n; i++){
        for(int j=0; j<=m; j++){
//            printf("%d %d: %lld %d / %lld %d\n", i, j, near[i][j][0], nearIdx[i][j][0], near[i][j][1], nearIdx[i][j][1]);
        }
    }

    priority_queue<cont> pq;
    pq.push(cont(x[1], y[1], 4, 1, 0));

    while(!pq.empty()){
        cont tmp = pq.top(); pq.pop();
        if(distIdx[tmp.x][tmp.y][tmp.d][1] != -1 || distIdx[tmp.x][tmp.y][tmp.d][0] == tmp.i) continue;
        int u = (distIdx[tmp.x][tmp.y][tmp.d][0] == -1) ? 0 : 1;
        dist[tmp.x][tmp.y][tmp.d][u] = tmp.dist;
        distIdx[tmp.x][tmp.y][tmp.d][u] = tmp.i;

        ans = min(ans, tmp.dist + c * (abs(tmp.x-x[k]) + abs(tmp.y-y[k])));
//        printf("%lld %lld %d %d: %lld\n", tmp.x, tmp.y, tmp.d, u, tmp.dist);

        if(tmp.d == 4){ /// 현재 선수가 공을 가지고 있다.
            for(int d=0; d<4; d++){
                ll tx = tmp.x + xx[d], ty = tmp.y + yy[d];
                if(tx<0||tx>n||ty<0||ty>m) continue;
                { /// d번 방향으로 한 칸 이동하기
                    if(distIdx[tx][ty][4][1] != -1 || distIdx[tx][ty][4][0] == tmp.i) continue;
                    pq.push(cont(tx, ty, 4, tmp.i, tmp.dist + c));
                }
                { /// d번 방향으로 공 굴리기
                    if(distIdx[tx][ty][d][1] != -1 || distIdx[tx][ty][d][0] == tmp.i) continue;
                    pq.push(cont(tx, ty, d, tmp.i, tmp.dist + a + b));
                }
            }
        }
        else{
            { /// 공이 계속 굴러가게 하기
                int d = tmp.d;
                ll tx = tmp.x + xx[d], ty = tmp.y + yy[d];
                if(!(tx<0 || tx>n || ty<0 || ty>m)){
                    if(distIdx[tx][ty][d][1] != -1 || distIdx[tx][ty][d][0] == tmp.i) continue;
                    pq.push(cont(tx, ty, d, tmp.i, tmp.dist + a));
                }
            }
            { /// 공을 선수가 잡기
                for(int u=0; u<2; u++){
                    if(tmp.i == nearIdx[tmp.x][tmp.y][u]) continue;
                    pq.push(cont(tmp.x, tmp.y, 4, nearIdx[tmp.x][tmp.y][u], tmp.dist + near[tmp.x][tmp.y][u] * c));
                }
            }
        }
    }

    printf("%lld", ans);
}

Compilation message (stderr)

soccer.cpp: In function 'int main()':
soccer.cpp:75:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   75 |     scanf("%d %d %lld %lld %lld %d", &n, &m, &a, &b, &c, &k);
      |     ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
soccer.cpp:76:34: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   76 |     for(int i=1; i<=k; i++) scanf("%lld %lld", &x[i], &y[i]);
      |                             ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...