tips:就是要用~~表示刪除 太蒻了
現在有一張圖, 有 v<=300v<=300 個節點
你需要從 c1c1 到 c2c2 到 cn(n<=2000)cn(n<=2000)
現在你有 mm 次機會把 cici 換爲 didi, 對於第 ii 個, 成功的概率爲 kiki
求走完整個路程的期望路徑長度
本題爲期望 dpdp , 從上一個狀態轉移過來(聽dalao說還有一種是計算本狀態對後面狀態的貢獻)
具體來說, 這個狀態可以由以上 nn 個狀態得到, 每個狀態權值爲 wiwi, 其中第 ii 個狀態到此狀態的概率爲 kiki, 那麼有此狀態可以表示爲
dp[now]=∑i=1nwi∗ki
本題狀態爲:
dp[i][j][0/1]dp[i][j][0/1] 代表選到第 ii 門課用掉 jj 次機會, 此次申請或不申請的期望值
所有轉移詳細記錄在註釋中
答案自然在 minmi=0min(dp[n][i][0],dp[n][i][1])
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define REP(i, x, y) for(int (i) = (x);(i) <= (y);(i)++)
using namespace std;
int RD(){
int out = 0,flag = 1;char c = getchar();
while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
return flag * out;
}
const int maxn = 4019, maxv = 319;
int num, numc, numv, nr;
int map[maxv][maxv];
int c[maxn], d[maxn];
double k[maxn];
double dp[maxn][maxn][2];
void floyd(){
REP(i, 1, numv)map[i][i] = 0;
REP(k, 1, numv)REP(i, 1, numv)REP(j, 1, numv){
map[i][j] = min(map[i][j], map[i][k] + map[k][j]);
}
}
int dist(int x, int y){return map[x][y];}
void init(){
REP(i, 1, numv)REP(j, 1, numv)map[i][j] = 1e9;
REP(i, 1, num)REP(j, 0, numc)dp[i][j][0] = dp[i][j][1] = 1e9;
}
int main(){
num = RD(), numc = RD(), numv = RD(), nr = RD();
init();
REP(i, 1, num)c[i] = RD();
REP(i, 1, num)d[i] = RD();
REP(i, 1, num)cin>>k[i];
REP(i, 1, nr){
int u = RD(), v = RD(), dis = RD();
map[u][v] = min(map[u][v], dis);
map[v][u] = map[u][v];
}
floyd();
dp[1][0][0] = dp[1][1][1] = 0;//選或不選都爲起點
REP(i, 2, num){
int m = min(numc, i);
REP(j, 0, m){//可以不申請換教室, 從0開始
dp[i][j][0] = min(//本次不申請
dp[i - 1][j][0] + dist(c[i], c[i - 1]),//上次不申請
dp[i - 1][j][1]//上次申請
+ dist(c[i], d[i - 1]) * k[i - 1]//申請成功
+ dist(c[i], c[i - 1]) * (1 - k[i - 1])//申請失敗
);
if(!j)continue;
dp[i][j][1] = min(//本次申請
dp[i - 1][j - 1][0]//上次不申請
+ dist(d[i], c[i - 1]) * k[i]//本次成功
+ dist(c[i], c[i - 1]) * (1 - k[i]), //本次失敗
dp[i - 1][j - 1][1]//上次申請
+ dist(c[i], c[i - 1]) * (1 - k[i]) * (1 - k[i - 1])//0->0
+ dist(d[i], c[i - 1]) * k[i] * (1 - k[i - 1])//0->1
+ dist(c[i], d[i - 1]) * (1 - k[i]) * k[i - 1]//1->0
+ dist(d[i], d[i - 1]) * k[i] * k[i - 1]//1->1
);
}
}
double ans = 100000019;
REP(i, 0, numc){
ans = min(ans, dp[num][i][0]);
ans = min(ans, dp[num][i][1]);
}
printf("%.2lf\n", ans);
return 0;
}