題目描述
蒜頭君是乙個樂於助人的好孩子,這天他所在的鄉村發生了洪水,有多名村民被困於孤島上,於是蒜頭君決定去揹他們離開困境,假設蒜頭君所在的村子是 n×輸入格式m 的網格,網格中.號代表平地,#號代表該地已被洪水淹沒,a、b……等大寫字母表示該地有村民被困,s代表蒜頭君的起點,t代表蒜頭君的終點。
蒜頭君的初始速度為 k 秒一格,他每次可以向上下左右 4 個方向中的乙個移動 1 格。在背上乙個村民後,他的速度可能會降低,也可能會加快,但他的速度不能快於 1 秒每格,那麼蒜頭君想知道,他最快需要多長時間將所有村民救出?
注意:不能在終點以外的地方放下村民;可以同時背多個村民。
第一行 3 個正整數 n,輸出格式m(1≤
n,m≤
10),k
,分別表示村莊長度、寬度、蒜頭君初始速度。
接下來
n 行,每行乙個長度為
m的字串,表示村莊的地形,字串意義如上所述。
接下來若干行,每行乙個大寫字母、乙個整數,表示該編號的村民會使
k 增加 / 減少多少。行數等同於地形中大寫字母的個數。大寫字母按字典序,即a、b、c的順序排列,保證前後兩行的字母是連續的,村民個數小於等於 10。
輸出 1 個整數,表示最小用時。樣例輸入
4 4 2樣例輸出 資料規模這麼小,不是搜尋就是狀壓。s.##
..a#
.b##
…t a -3
b 4
標程給出的是三進製狀壓dp,但是這樣做使得位運算的優勢不復存在了。所以時間複雜度其實也只是理性愉悅,提取某一位常數很大。而且也增加了程式設計複雜度。
事實上二進位制狀壓dp是可以的,並不會達到o(
4cnt
cnt2
) 的複雜度,而且跑得很快。
定義狀態f[
s1][
s2][
p]表示揹著的村民狀態為s1
,已經到終點的村民為s2
,蒜頭君處在
p 位置(
p只取初始狀態下村民的位置、終點位置),那麼顯然有狀態轉移: f[
s1|(
1<
1)][
s2][
y]=m
in(d
is(x
,y)v
[s1]
+f[s
1][s
2][x
]) (
x∉s2
,x∈s
1,y∉
s2,y
∉s1)
f[s1xor
t][s
2|t]
[en]
=min
(f[s
1xor
t][s
2|t]
[en]
,f[s
1][s
2][e
n])
(t∈s
1,en
為終點)
v[s] 表示在揹著的村民狀態為
s 下的速度,di
s(x,
y)表示在原圖上x,
y 的距離。都可以預處理出來。下面的**採用的是floyd求距離,當然也可以用bfs。
上述兩式分別表示到乙個地方接村民、在終點放村民。如果不用記憶化搜尋的形式,注意迴圈順序。
那麼為什麼跑得很快呢?因為在這樣的定義下,s1
與s2 是不能有交集的,這樣顯然不可能的情況在迴圈裡判斷一下就可以了,實際上可能合法的情況只有3c
nt種。再加上x,
y 與兩個集合間的關係,迴圈執行的次數不會特別多。
**:
#include
#include
#include
using namespace std;
int n,m,k,dx[4]=,dy[4]=;
int map[105][105],pos[15],id[15][15],tot,v[15];
int f[1234][1234][15],v[1234],u,inf;
char s[15][15];
int main()}}
for(k=1;k<=tot;k++)
for(i=1;i<=tot;i++)
for(j=1;j<=tot;j++)map[i][j]=min(map[i][j],map[i][k]+map[k][j]);
//floyd預處理距離
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
u=(1
<0])-1;
v[0]=k;
for(i=1;i<=u;i++)
//預處理v
memset(f,60,sizeof(f));
for(i=1;i<=v[0];i++)f[1
<1][0][i]=map[st][pos[i]]*k;
f[0][0][v[0]+1]=map[st][pos[v[0]+1]]*k;
inf=f[0][0][0];
for(j=0;jfor(i=0;i<=u;i++)
y=v[0]+1;
if(f[i][j][y]>f[i][j][x]+v[i]*map[pos[x]][pos[y]])f[i][j][y]=f[i][j][x]+v[i]*map[pos[x]][pos[y]];
}for(x=i;x;x=x-1&i)f[i^x][j|x][v[0]+1]=min(f[i^x][j|x][v[0]+1],f[i][j][v[0]+1]);//列舉子集
}printf("%d",f[0][u][v[0]+1]);
}
蒜頭君救人
問題 蒜頭君是乙個樂於助人的好孩子,這天他所在的鄉村發生了洪水,有多名村民被困於孤島上,於是蒜頭君決定去揹他們離開困境,假設蒜頭君所在的村子是 n mn m 的網格,網格中.號代表平地,號代表該地已被洪水淹沒,a b 等大寫字母表示該地有村民被困,s代表蒜頭君的起點,t代表蒜頭君的終點。蒜頭君的初始...
noip模擬賽 蒜頭君救人
分析 之前的一道模擬賽題是dp dfs,這道題是dp bfs.我們設f stu i j 為當前狀態為stu,走到 i,j 的答案,考慮怎麼設計stu,每個人的狀態有3種 要麼在原地,要麼被揹著,要麼已經到了終點,那麼用乙個3進製數儲存就可以了.下面考慮怎麼轉移,直接遞推肯定是不對的,dfs也不行,只...
狀壓dp 玉公尺田 狀壓dp
相關 強相關 327.玉公尺田 狀壓dp 小國王 狀壓dp 是井字形,本題是十字形。思路 狀態計算 時間複雜度 n 2 n 2n o n 22n 12 2 24n 2 n 2 n o n2 12 2 n 2n 2 n o n22n 12 224 看著妥妥超時,但是裡面合法狀態很少 依舊可以過 在此,...