您的位置:首页 > 其它

Codeforces Round #420 (Div. 2) D. Okabe and City (最短路)

2017-06-27 17:05 471 查看
终于下定决心要写博客了,希望自己能坚持下去。

题意:n*m的方格里有k个方格是亮着的。主角要从(1,1)走到(n,m),只能走亮的格子。每次主角可以用一个硬币点亮一行或者一列的格子,但点亮下一行或下一列的时候,上次点亮的效果会消失。而且,改变点亮的行和列的时候,必须站在原来就亮着的格子。求最少支付的硬币数,无解输出-1。

做法很简单,除正常的建图之外,把每一行和一列都看成一个点,相邻的亮着的格子到这个点建两条有向边,格子到行列权是1,行列到格子权是0。跑一遍最短路即可。

现场SB了。。赛后再写很快就1A。

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define INF 0x3f3f3f3fLL
typedef pair< int, int > pii;
typedef long long ll;
int encode(int x, int y){ return x * 100000 + y; }
void decode(int a, int& x, int& y) { x = a / 100000; y = a % 100000; }
set<int>s;
map<int, int>mp;
int now = 0;
vector<int>v[100005];
vector<int>c[100005];
const int stepx[4] = {1,0,-1,0};
const int stepy[4] = {0,1,0,-1};
int n, m, k;
int dis[100005];
bool vis[100005];
queue<int>q;
bool check(int x, int y){
if (x >= 1 && x <= n && y >= 1 && y <= m) return 1;
else return 0;
}
int main(){
ios::sync_with_stdio(0);
cin >> n >> m >> k;
int S = -1, T = -1;
for (int i = 0; i < k; i++){
int x, y; cin >> x >> y;
s.insert(encode(x, y));
if (x == 1 && y == 1) S = now;
if (x == n && y == m) T = now;
mp[encode(x, y)] = now++;
}
int rowstart = now - 1;
int colstart = now + n - 1;
for (set<int>::iterator it = s.begin(); it != s.end(); it++){
int x, y; decode(*it, x, y);
for (int i = 0; i < 4; i++){
int newx = x + stepx[i];
int newy = y + stepy[i];
if (check(newx, newy) && s.find(encode(newx, newy)) != s.end()){
v[mp[encode(newx, newy)]].push_back(mp[*it]);
c[mp[encode(newx, newy)]].push_back(0);
v[mp[*it]].push_back(mp[encode(newx, newy)]);
c[mp[*it]].push_back(0);
}
}
for (int i = max(1, x - 1); i <= min(n, x + 1); i++){
v[rowstart + i].push_back(mp[*it]);
c[rowstart + i].push_back(0);
v[mp[*it]].push_back(rowstart + i);
c[mp[*it]].push_back(1);
}
for (int i = max(1, y - 1); i <= min(m, y + 1); i++){
v[colstart + i].push_back(mp[*it]);
c[colstart + i].push_back(0);
v[mp[*it]].push_back(colstart + i);
c[mp[*it]].push_back(1);
}
}
for (int i = 0; i < 100005; i++) {vis[i] = 0; dis[i] = INF;}
dis[S] = 0; q.push(S);
while (!q.empty()){
int now = q.front(); q.pop();
vis[now] = 0;
for (int i = 0; i < v[now].size(); i++){
if (dis[v[now][i]] > dis[now] + c[now][i]){
dis[v[now][i]] = dis[now] + c[now][i];
if (!vis[v[now][i]]){
q.push(v[now][i]); vis[v[now][i]] = 1;
}
}
}
}
int ans = INF;
if (T != -1) ans = dis[T];
else ans = min(dis[rowstart + n], dis[colstart + m]);
if (ans == INF) ans = -1;
cout << ans << endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息