记录一个菜逼的成长。。
题目大意:
给你n*m的矩阵
‘W’表示水,其他表示国家
问这些国家最少需要走多少步,才能到达边界与水相邻的国家
国家这么多,水就一种,我们不妨反着求。
求从水到这些国家的最短路
这里就有两种算法
一种就是spfa算法
测试了无优化,SLF优化,SLF+LLL优化
实际上这里还是SLF优化快
#include <bits/stdc++.h>
using namespace std;
#define ALL(v) (v).begin(),(v).end()
#define cl(a,b) memset(a,b,sizeof(a))
#define clr clear()
#define pb push_back
#define mp make_pair
#define fi first
#define se second
typedef long long LL;
typedef pair<int,int> PII;
const int INF = 0x3f3f3f3f;
const int maxn = 1000 + 10;
char str[maxn][maxn];
int vis[maxn][maxn],dis[maxn][maxn],n,m;
int ans[30];
int dx[] = {-1,-1,0,1,1,1,0,-1},dy[] = {0,1,1,1,0,-1,-1,-1};
deque<PII>q;
void spfa()
{
while(!q.empty()){
PII f = q.front();q.pop_front();
vis[f.fi][f.se] = 0;
for( int i = 0; i < 8; i++ ){
int nx = f.fi + dx[i],ny = f.se + dy[i];
if(nx < 1 || nx > n || ny < 1 || ny > m)continue;
int w = (str[nx][ny] != str[f.fi][f.se]);
if(dis[nx][ny] > dis[f.fi][f.se] + w){
dis[nx][ny] = dis[f.fi][f.se] + w;
if(!vis[nx][ny]){
vis[nx][ny] = 1;
///SLF优化
if(dis[nx][ny] < dis[q.front().fi][q.front().se]){
q.push_front(mp(nx,ny));
}
else {
q.push_back(mp(nx,ny));
}
}
}
}
}
}
void init()
{
cl(dis,INF);
cl(vis,0);
cl(ans,INF);
}
int main()
{
while(~scanf("%d%d",&n,&m)){
init();
for( int i = 1; i <= n; i++ ){
scanf("%s",str[i]+1);
for( int j = 1; j <= m; j++ ){
if(str[i][j] == 'W'){
if(!vis[i][j]){
vis[i][j] = 1;
dis[i][j] = 0;
q.push_back(mp(i,j));
}
}
}
}
spfa();
for( int i = 1; i <= n; i++ ){
for( int j = 1; j <= m; j++ ){
if(str[i][j] != 'W'){
ans[str[i][j]-'A'] = min(ans[str[i][j]-'A'] , dis[i][j]);
}
}
}
for( int i = 0; i < 26; i++ ){
if(ans[i] != INF){
printf("%c %d\n",i+'A',ans[i]-1);
}
}
}
return 0;
}
另一种是堆优化的dijkstra算法
优先队列的比较结构定义
/// One of the @link comparison_functors comparison functors@endlink.
template<typename _Tp>
struct greater : public binary_function<_Tp, _Tp, bool>
{
bool operator()(const _Tp& __x, const _Tp& __y) const
{ return __x > __y; }
};
/// One of the @link comparison_functors comparison functors@endlink.
template<typename _Tp>
struct less : public binary_function<_Tp, _Tp, bool>
{
bool operator()(const _Tp& __x, const _Tp& __y) const
{ return __x < __y; }
};
#include <bits/stdc++.h>
using namespace std;
#define ALL(v) (v).begin(),(v).end()
#define cl(a,b) memset(a,b,sizeof(a))
#define clr clear()
#define pb push_back
#define mp make_pair
#define fi first
#define se second
typedef long long LL;
typedef pair<int,int> PII;
const int INF = 0x3f3f3f3f;
const int maxn = 1000 + 10;
char str[maxn][maxn];
int vis[maxn][maxn],dis[maxn][maxn],n,m;
int ans[30];
int dx[] = {-1,-1,0,1,1,1,0,-1},dy[] = {0,1,1,1,0,-1,-1,-1};
struct Node{
int dis,x,y;
Node(){}
Node(int d,int xx,int yy):dis(d),x(xx),y(yy){}
//小顶堆
friend bool operator > (const Node& a,const Node& b){
return a.dis > b.dis;
}
//大顶堆
friend bool operator < (const Node& a,const Node& b){
return a.dis < b.dis;
}
};
struct cmp{
bool operator()(const Node &a,const Node &b)const{
return a.dis > b.dis;//小顶堆,, 改成<是大顶堆
}
};
//优先队列这里有两种定义优先级的方法
priority_queue<Node,vector<Node>,greater<Node> >q;//如果是重载运算符就用这种形式
//priority_queue<Node,vector<Node>,cmp>q;//如果是定义结构,用这种形式
void dijkstra()
{
while(!q.empty()){
Node f = q.top();q.pop();
vis[f.x][f.y] = 0;
for( int i = 0; i < 8; i++ ){
int nx = f.x + dx[i],ny = f.y + dy[i];
if(nx < 1 || nx > n || ny < 1 || ny > m)continue;
int w = (str[nx][ny] != str[f.x][f.y]);
if(dis[nx][ny] > dis[f.x][f.y] + w){
dis[nx][ny] = dis[f.x][f.y] + w;
if(!vis[nx][ny]){
vis[nx][ny] = 1;
q.push(Node(dis[nx][ny],nx,ny));
}
}
}
}
}
void init()
{
cl(dis,INF);
cl(vis,0);
cl(ans,INF);
}
int main()
{
while(~scanf("%d%d",&n,&m)){
init();
for( int i = 1; i <= n; i++ ){
scanf("%s",str[i]+1);
for( int j = 1; j <= m; j++ ){
if(str[i][j] == 'W'){
if(!vis[i][j]){
vis[i][j] = 1;
dis[i][j] = 0;
q.push(Node(0,i,j));
}
}
}
}
dijkstra();
for( int i = 1; i <= n; i++ ){
for( int j = 1; j <= m; j++ ){
if(str[i][j] != 'W'){
ans[str[i][j]-'A'] = min(ans[str[i][j]-'A'] , dis[i][j]);
}
}
}
for( int i = 0; i < 26; i++ ){
if(ans[i] != INF){
printf("%c %d\n",i+'A',ans[i]-1);
}
}
}
return 0;
}