1. 程式人生 > >Codeforces Round #355D (Div. 2) 暴力+BFS

Codeforces Round #355D (Div. 2) 暴力+BFS

題意:你一開始在(1,1),有n*m個地方,去X以前必須要去X-1

思路:這題很迷。。我確實是不會做。。看來BFS分類的思路實現了一下過了,這題直接暴力是n^4肯定是不行的,當然顯然直接BFS也不行,就算有剪枝最壞情況仍然很糟糕(當出發點很多的時候剪枝效果顯然會變好),所以考慮以n*m為分界分別採用兩種策略。。

於是就神奇的水過去了。。

講講其他思路。。神奇的水過去的方法是在暴力裡面排序一下,然後只去前600左右進行比較一下(似乎是資料弱的過)。。還有一種方法是四個方向建立四個二維BIT。感覺很神奇。。仍在學習中。。

分類+bfs程式碼:

#include <bits/stdc++.h>

using namespace std;

int n,m,p;
const int inf=0x3f3f3f3f;
int mp[305][305];
vector<pair<int,int> > post[305*305];
vector<int> dp[305*305];
int vis[305][305];

struct node{
    int t,x,y;
    node(int T,int X,int Y):t(T),x(X),y(Y){};
};

void BFS(int z){
    memset(vis,inf,sizeof(vis));
    queue<node> Q;
    for(int i=0;i<post[z].size();i++){
       Q.push(node(dp[z][i],post[z][i].first,post[z][i].second));
       vis[post[z][i].first][post[z][i].second]=dp[z][i];
    }
    while(!Q.empty()){
        node top=Q.front();
        Q.pop();
        if((top.x-1>0&&top.x-1<=n&&top.y>0&&top.y<=m)&&(vis[top.x-1][top.y]>top.t+1)){
            Q.push(node(top.t+1,top.x-1,top.y));
            vis[top.x-1][top.y]=top.t+1;
        }
        if((top.x+1>0&&top.x+1<=n&&top.y>0&&top.y<=m)&&(vis[top.x+1][top.y]>top.t+1)){
            Q.push(node(top.t+1,top.x+1,top.y));
            vis[top.x+1][top.y]=top.t+1;
        }
        if((top.x>0&&top.x<=n&&top.y-1>0&&top.y-1<=m)&&(vis[top.x][top.y-1]>top.t+1)){
            Q.push(node(top.t+1,top.x,top.y-1));
            vis[top.x][top.y-1]=top.t+1;
        }
        if((top.x>0&&top.x<=n&&top.y+1>0&&top.y+1<=m)&&(vis[top.x][top.y+1]>top.t+1)){
            Q.push(node(top.t+1,top.x,top.y+1));
            vis[top.x][top.y+1]=top.t+1;
        }
    }
    for(int i=0;i<post[z+1].size();i++) dp[z+1][i]=vis[post[z+1][i].first][post[z+1][i].second];
}

int main(){
    cin>>n>>m>>p;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>mp[i][j];
            post[mp[i][j]].push_back(make_pair(i,j));
            dp[mp[i][j]].push_back(inf);
        }
    }
    post[0].push_back(make_pair(1,1));
    dp[0].push_back(0);
    for(int i=0;i<p;i++){
        if(post[i].size()*post[i+1].size()>n*m) BFS(i);
        else{
            for(int j=0;j<post[i+1].size();j++){
                for(int k=0;k<post[i].size();k++){
                    dp[i+1][j]=min(dp[i+1][j],abs(post[i+1][j].first-post[i][k].first)+abs(post[i+1][j].second-post[i][k].second)+dp[i][k]);
                }
            }
        }
    }
    int ans=inf;
    for(int i=0;i<dp[p].size();i++) ans=min(ans,dp[p][i]);
    cout<<ans<<endl;
    return 0;
}