Submission #685421

#TimeUsernameProblemLanguageResultExecution timeMemory
685421coffee5427Soccer (JOI17_soccer)C++17
100 / 100
672 ms105876 KiB
#include <queue>
#include <vector>
#include <stdio.h>
#include <iostream>
#include <algorithm>
#define INF 0x3f3f3f3f
#define MAX 0x7f7f7f7f7f7f7f7f
using namespace std;
typedef long long ll;
const int W = 505;
const int N = 100005;

struct Node{ int x; ll y; };
struct player{ int x, y; }P[N];
struct Edge{ int to, next; ll weight; }edge[W * W * 36];
struct cmp{ bool operator()(Node x, Node y){ return x.y > y.y; } };

ll dis[W * W * 6], ans = MAX;
bool vis[W][W], vis2[W * W * 6];
int h, w, a, b, c, n, sum, cnt = 1;
int dx[4] = { 1, -1, 0, 0 };
int dy[4] = { 0, 0, 1, -1 };
int head[W * W * 6], dt[W][W];
int ctt = 0;

template<typename T> inline void read(T &x)
{
    x = 0; char ch = getchar(); bool flag = false;
    while(ch < '0' || ch > '9'){if(ch == '-') flag = true; ch = getchar();}
    while('0' <= ch && ch <= '9'){x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    if(flag) x = -x;
}

inline void add(int u, int v, ll w)
{
  // cout << "u:" << u << ",v:" << v << ",w:" << w << "\n";
  //   ctt++;
  //   if (ctt > 20) exit(0);
    edge[cnt].to = v, edge[cnt].weight = w;
    edge[cnt].next = head[u], head[u] = cnt++;
}

inline ll Min(ll x, ll y){ return x < y ? x : y; }
inline int id(int x, int y){ return x * (w + 1) + y; } //用一個數字表示一個平面座標 

inline void Manhattan_Distance()
{
    queue<player> q;
    for(register int i = 0;i <= h;i++) for(register int j = 0;j <= w;j++) dt[i][j] = INF;
    for(register int i = 1; i <= n; i++){ dt[P[i].x][P[i].y] = 0; q.push(P[i]); }
    while(!q.empty())
    {
        int x = q.front().x, y = q.front().y;
        q.pop(); vis[x][y] = false;
        for(register int i = 0; i < 4; i++)
        {
            int xx = x + dx[i], yy = y + dy[i];
            if(xx >= 0 && xx <= h && yy >= 0 && yy <= w && dt[xx][yy] > dt[x][y] + 1)
            {
                dt[xx][yy] = dt[x][y] + 1;
                if(!vis[xx][yy])
                {
                    player graph;
                    graph.x = xx, graph.y = yy;
                    q.push(graph);  vis[xx][yy] = true;
                }
            }
        }
    }
}

inline void Dijkstra()
{
    priority_queue<Node, vector<Node>, cmp> q;
    for(register int i = 0;i <= W * W * 6;i++) dis[i] = MAX;
    Node graph; graph.x = id(P[1].x, P[1].y) + 4 * sum, graph.y = 0;
    q.push(graph); dis[id(P[1].x, P[1].y) + 4 * sum] = 0;
    while(!q.empty())
    {
        int x = q.top().x;
        q.pop(); if(!vis2[x])
        {
            vis2[x] = true;
            for(register int i = head[x];i != 0;i = edge[i].next)
            {
                int v = edge[i].to;
                if (dis[v] > dis[x] + edge[i].weight)
                {
                    dis[v] = dis[x] + edge[i].weight; Node graph;
                    graph.x = v, graph.y = dis[v];
                    q.push(graph);
                }
            }
        }
    }
}

int main()
{
    read(h), read(w), read(a), read(b), read(c), read(n);
    for(register int i = 1; i <= n; i++) read(P[i].x), read(P[i].y);
    Manhattan_Distance();
    sum = (w + 1) * (h + 1); //因爲橫縱座標可以爲0,所以要+1
	//通過k * sum的表示方法拆點 
    for(register int i = 0; i <= h; i++)
    {
        for(register int j = 0; j <= w; j++)
        {
            int p = id(i, j);
            for(register int k = 0; k < 4; k++)
            {
              //cout << "p:" << p << ",k:" << k << ",sum:" << sum << "\n";
                add(p + k * sum, p + 4 * sum, 0); //球從滾動狀態(無人控球)到停止 
                add(p + 5 * sum, p + k * sum, b); //球從靜止狀態(有人控球)到將球傳出 
                add(p + 4 * sum, p + 5 * sum, c * (ll)dt[i][j]); //離球最近的球員(曼哈頓距離)跑過來控球 
				int xx = i + dx[k], yy = j + dy[k];
        // cout << "k:" << k << "\n";
        // cout << "p:" "(" << i << "," << j << ")" << "\n";
        // cout << "q:" << "(" << xx << "," << yy << ")" << "\n";
                if(xx >= 0 && yy >= 0 && xx <= h && yy <= w)
                {
                    int q = id(xx, yy);
                    add(p + k * sum, q + k * sum, a); //球從一個位置按照其方向滾到相鄰的位置(傳球) 
                    add(p + 5 * sum, q + 5 * sum, c); //球從一個位置按照其方向滾到相鄰的位置(帶球) 
                }
            }
        }
    }
    Dijkstra();
    for(register int i = 0; i < 6; i++)
    {
        ans = Min(ans, dis[id(P[n].x, P[n].y) + i * sum]);
    }
    //printf("%lld\n", dis[id(P[1].x, P[0].y) + 1 * sum]);
    printf("%lld\n", ans);
    return 0;
}

Compilation message (stderr)

soccer.cpp: In function 'void Manhattan_Distance()':
soccer.cpp:49:22: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
   49 |     for(register int i = 0;i <= h;i++) for(register int j = 0;j <= w;j++) dt[i][j] = INF;
      |                      ^
soccer.cpp:49:57: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
   49 |     for(register int i = 0;i <= h;i++) for(register int j = 0;j <= w;j++) dt[i][j] = INF;
      |                                                         ^
soccer.cpp:50:22: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
   50 |     for(register int i = 1; i <= n; i++){ dt[P[i].x][P[i].y] = 0; q.push(P[i]); }
      |                      ^
soccer.cpp:55:26: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
   55 |         for(register int i = 0; i < 4; i++)
      |                          ^
soccer.cpp: In function 'void Dijkstra()':
soccer.cpp:75:22: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
   75 |     for(register int i = 0;i <= W * W * 6;i++) dis[i] = MAX;
      |                      ^
soccer.cpp:84:30: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
   84 |             for(register int i = head[x];i != 0;i = edge[i].next)
      |                              ^
soccer.cpp: In function 'int main()':
soccer.cpp:101:22: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
  101 |     for(register int i = 1; i <= n; i++) read(P[i].x), read(P[i].y);
      |                      ^
soccer.cpp:105:22: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
  105 |     for(register int i = 0; i <= h; i++)
      |                      ^
soccer.cpp:107:26: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
  107 |         for(register int j = 0; j <= w; j++)
      |                          ^
soccer.cpp:110:30: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
  110 |             for(register int k = 0; k < 4; k++)
      |                              ^
soccer.cpp:130:22: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
  130 |     for(register int i = 0; i < 6; i++)
      |                      ^
soccer.cpp: In function 'void Dijkstra()':
soccer.cpp:75:55: warning: iteration 1530150 invokes undefined behavior [-Waggressive-loop-optimizations]
   75 |     for(register int i = 0;i <= W * W * 6;i++) dis[i] = MAX;
      |                                                       ^
soccer.cpp:75:30: note: within this loop
   75 |     for(register int i = 0;i <= W * W * 6;i++) dis[i] = MAX;
      |                            ~~^~~~~~~~~~~~
soccer.cpp:75:55: warning: 'void* __builtin_memset(void*, int, long unsigned int)' forming offset [12241200, 12241207] is out of the bounds [0, 12241200] of object 'dis' with type 'll [1530150]' {aka 'long long int [1530150]'} [-Warray-bounds]
   75 |     for(register int i = 0;i <= W * W * 6;i++) dis[i] = MAX;
      |                                                       ^
soccer.cpp:18:4: note: 'dis' declared here
   18 | ll dis[W * W * 6], ans = MAX;
      |    ^~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...