題意:
電影院放映結束,場地爲的矩陣,且每個位置上都有人.
一個人離場時,只有他一個人能移動,假如他碰到了別人的位置,別人就會生氣.
一個人只有離開的矩陣,即到達邊界纔算離場完畢.
現在,給出一個離場順序,求出生氣人次的最小值.
設表示的人當前的最少得罪人數量.
初始時,顯然.
然後,每次一個人離開後暴力鬆弛這個最短路.
因爲初始的,所以複雜度正確,可以輕鬆跑過.
證明:
我們明顯可以把這個圖分割成8塊,所以我們只要求一塊的答案即可.
設,然後我們要求,
#include<map>
#include<queue>
#include<cmath>
#include<bitset>
#include<cstdio>
#include<vector>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define fi first
#define se second
#define lc (x<<1)
#define rc (x<<1|1)
#define gc getchar()
#define mk make_pair
#define pi pair<int,int>
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=510;
template<class o>void qr(o&x) {
char c=gc;int f=1;x=0;
while(!isdigit(c)){if(c=='-')f=-1;c=gc;}
while(isdigit(c))x=x*10+c-'0',c=gc;
x*=f;
}
template<class o>void qw(o x) {
if(x/10)qw(x/10);
putchar(x%10+'0');
}
template<class o> void pr1(o x) {
if(x<0)x=-x,putchar('-');
qw(x); putchar(' ');
}
template<class o>void pr2(o x) {
if(x<0)x=-x,putchar('-');
qw(x);puts("");
}
int n,d[N][N],ans;
bool f[N][N];
const int dx[]={1,-1,0,0};
const int dy[]={0,0,1,-1};
void dfs(int x,int y) {
for(int t=0;t<4;t++) {
int tx=x+dx[t],ty=y+dy[t];
if(tx&&tx<=n&&ty&&ty<=n&&d[tx][ty]>d[x][y]+f[x][y]) {
d[tx][ty]=d[x][y]+f[x][y];
dfs(tx,ty);
}
}
}
int main() {
qr(n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
ans+=(d[i][j]=min(min(i-1,n-i),min(j-1,n-j)));
ans=0; memset(f,1,sizeof f);
for(int i=1,t,x,y;i<=n*n;i++) {
qr(t); x=(t-1)/n+1; y=t-(x-1)*n;
ans+=d[x][y];f[x][y]=0; dfs(x,y);
}
pr2(ans);
return 0;
}