Acwing 274.移動服務 (DP)
阿新 • • 發佈:2020-08-03
題面
一個公司有三個移動服務員,最初分別在位置1,2,3處。
如果某個位置(用一個整數表示)有一個請求,那麼公司必須指派某名員工趕到那個地方去。
某一時刻只有一個員工能移動,且不允許在同樣的位置出現兩個員工。
從 p 到 q 移動一個員工,需要花費 c(p,q)。
這個函式不一定對稱,但保證 c(p,p)=0。
給出N個請求,請求發生的位置分別為 p1~pN。
公司必須按順序依次滿足所有請求,且過程中不能去其他額外的位置,目標是最小化公司花費,請你幫忙計算這個最小花費。
輸入格式
第1行有兩個整數L,N,其中L是位置數量,N是請求數量,每個位置從1到L編號。
第2至L+1行每行包含L個非負整數,第i+1行的第j個數表示c(i,j) ,並且它小於2000。
最後一行包含N個整數,是請求列表。
一開始三個服務員分別在位置1,2,3。
輸出格式
輸出一個整數M,表示最小花費。
資料範圍
3≤L≤200,
1≤N≤1000
輸入樣例:
5 9
0 1 1 1 1
1 0 2 3 2
1 1 0 4 1
2 1 5 0 1
4 2 3 4 0
4 2 4 1 5 4 3 2 1
輸出樣例:
5
思路
首先我們直接考慮四維陣列dp,但看起來會炸,那麼優化,我們其實可以壓縮成為三維的,因為這三個郵遞員裡面必定有一個是等於當前的要求的地點,所以我們不用單獨開一維去存。那麼接下來我們考慮狀態轉移,這道題目我們發現從後往前推並不是很方便,所以我們考慮用當前狀態去更新後面的狀態,那麼具體的轉移就是列舉是哪個郵遞員去了下一個地點,並且加上鄰接矩陣裡面的對應距離,就是下一個狀態的值了。要記得不能有多個郵遞員在同一地點的判斷哦。
程式碼實現
#include<cstdio> #include<algorithm> #include<vector> #include<queue> #include<map> #include<iostream> #include<cstring> #include<cmath> using namespace std; #define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i) #define per(i,n,a) for (int i=n;i>=a;i--) #define MT(x,i) memset(x,i,sizeof(x) ) #define rev(i,start,end) for (int i=0;i<end;i++) #define inf 0x3f3f3f3f #define mp(x,y) make_pair(x,y) #define lowbit(x) (x&-x) #define MOD 1000000007 #define exp 1e-8 #define N 1000005 #define fi first #define se second #define pb push_back typedef long long ll; typedef pair<int ,int> PII; ll gcd (ll a,ll b) {return b?gcd (b,a%b):a; } inline int read() { char ch=getchar(); int x=0, f=1; while(ch<'0'||ch>'9') { if(ch=='-') f = -1; ch=getchar(); } while('0'<=ch&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } const int maxn=201; const int M=1010; int f[M][maxn][maxn]; int maze[maxn][maxn]; int n,m; int ask[M]; int main () { cin>>n>>m; rep (i,1,n) rep (j,1,n) { cin>>maze[i][j]; } MT (ask,0); rep (i,1,m) cin>>ask[i]; ask[0]=3; int ans=0x3f3f3f3f; MT (f,0x3f); f[0][1][2]=0; rev (i,0,m) rep (x,1,n) rep (y,1,n) { int z=ask[i],u=ask[i+1],w=f[i][x][y]; if (x==y||y==z||x==z) continue; f[i+1][x][y]=min (f[i+1][x][y],w+maze[z][u]); f[i+1][x][z]=min (f[i+1][x][z],w+maze[y][u]); f[i+1][z][y]=min (f[i+1][z][y],w+maze[x][u]); } rep (i,1,n) rep (j,1,n) { int z=ask[m]; if (i==j||j==z||z==i) continue; ans=min (ans,f[m][i][j]); } cout<<ans<<endl; return 0; }