CCF CSP 201409-4 最優配餐

CCF計算機職業資格認證考試題解系列文章爲 meelo原創,請務必以連接形式註明 本文地址

CCF CSP 201409-4 最優配餐

問題描述

  棟棟最近開了一家餐飲連鎖店,提供外賣服務。隨着連鎖店愈來愈多,怎麼合理的給客戶送餐成爲了一個急需解決的問題。
  棟棟的連鎖店所在的區域能夠當作是一個n×n的方格圖(以下圖所示),方格的格點上的位置上可能包含棟棟的分店(綠色標註)或者客戶(藍色標註),有一些格點是不能通過的(紅色標註)。
  方格圖中的線表示能夠行走的道路,相鄰兩個格點的距離爲1。棟棟要送餐必須走能夠行走的道路,並且不能通過紅色標註的點。


  送餐的主要成本體如今路上所花的時間,每一份餐每走一個單位的距離須要花費1塊錢。每一個客戶的需求均可以由棟棟的任意分店配送,每一個分店沒有配送總量的限制。
  如今你獲得了棟棟的客戶的需求,請問在最優的送餐方式下,送這些餐須要花費多大的成本。

輸入格式

  輸入的第一行包含四個整數n, m, k, d,分別表示方格圖的大小、棟棟的分店數量、客戶的數量,以及不能通過的點的數量。
  接下來m行,每行兩個整數xi, yi,表示棟棟的一個分店在方格圖中的橫座標和縱座標。
  接下來k行,每行三個整數xi, yi, ci,分別表示每一個客戶在方格圖中的橫座標、縱座標和訂餐的量。(注意,可能有多個客戶在方格圖中的同一個位置)
  接下來d行,每行兩個整數,分別表示每一個不能通過的點的橫座標和縱座標。

輸出格式

  輸出一個整數,表示最優送餐方式下所須要花費的成本。

樣例輸入

10 2 3 3
1 1
8 8
1 5 1
2 3 3
6 7 2
1 2
2 2
6 8

樣例輸出

29

評測用例規模與約定

  前30%的評測用例知足:1<=n <=20。
  前60%的評測用例知足:1<=n<=100。
  全部評測用例都知足:1<=n<=1000,1<=m, k, d<=n^2。可能有多個客戶在同一個格點上。每一個客戶的訂餐量不超過1000,每一個客戶所須要的餐都能被送到。

解析

題目能夠使用廣度優先搜索解決。
不一樣於普通的廣度優先搜索,初始隊列的位置不是一個點而是多個點,也就是從多個店的位置同時開始廣度優先搜索。
能夠把方格中每個點到最近商店的距離保存到矩陣裏,最後再遍歷客戶計算成本。
須要注意的是,結果會超過int的表示範圍。

代碼

C++html

#include "iostream"
#include "vector"
#include "queue"

using namespace std;

int dist[1001][1001];
bool visited[1001][1001];
int width, numStore, numClient, numHole;

struct Pos {
  int x, y, val;
  Pos(int _x, int _y): x(_x), y(_y) {}
  Pos() {}
};

bool legal(int x, int y) {
  return x>=1 && y>=1 && x<=width && y<=width;
}

Pos dir[4] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};

int main() {
  cin >> width >> numStore >> numClient >> numHole;
  
  queue<Pos> stores;
  vector<Pos> holes, clients;
  
  Pos p;
  for(int i=0; i<numStore; i++) {
    cin >> p.x >> p.y;
    stores.push(p);
    dist[p.x][p.y] = 0;
    visited[p.x][p.y] = true;
  }
  for(int i=0; i<numClient; i++) {
    cin >> p.x >> p.y >> p.val;
    clients.push_back(p);
  }
  for(int i=0; i<numHole; i++) {
    cin >> p.x >> p.y;
    dist[p.x][p.y] = -1;
    visited[p.x][p.y] = true;
  }
  while(!stores.empty()) {
    Pos p = stores.front();
    stores.pop();
    for(int i=0; i<4; i++) {
      Pos np(p.x+dir[i].x, p.y+dir[i].y);
      if(!visited[np.x][np.y] && legal(np.x, np.y)) {
        visited[np.x][np.y] = true;
        dist[np.x][np.y] = dist[p.x][p.y] + 1;
        stores.push(np);
      }
    }
  }
  long long cost = 0;
  for(int i=0; i<numClient; i++) {
    cost += dist[clients[i].x][clients[i].y] * clients[i].val;
  }
  cout << cost;
}
相關文章
相關標籤/搜索