洛谷 P1850 [NOIP 2016 提高組] 換教室


題目傳送門


前言

終于自己想出概率期望 d p dp dp 的狀態了,但是依舊沒能相對轉移方程。(招笑)


暴力

這題部分分和特殊情況分給的挺多的,所以先拿部分分。

一、思路

  1. 先跑一邊 F l o y d Floyd Floyd 最短路求出兩點間最短距離 d i s i , j dis_{i, j} disi,j?
  2. 對于 m = 0 m = 0 m=0,答案就是 ∑ i = 1 n ? 1 d i s c i , c i + 1 \sum_{i = 1}^{n - 1} dis_{c_{i}, c_{i + 1}} i=1n?1?disci?,ci+1??
    對于所有 n ≤ 20 n \leq 20 n20,直接用狀態壓縮,二進制枚舉所有 【申請情況】【同意情況】(注意:這兩者不一樣,因為申請了不一定同意,所以枚舉申請情況之下還要枚舉同意情況),直接計算。

二、復雜度

  1. 空間: O ( v 2 + n ) O(v^2 + n) O(v2+n)
  2. 時間:對于 m = 0 m = 0 m=0 O ( v 3 + n ) O(v^3 + n) O(v3+n);對于 n ≤ 20 n \leq 20 n20 O ( v 3 + n × 2 n × 2 m ) O(v^3 + n \times 2^n \times 2^m) O(v3+n×2n×2m)
    (當然后者的時間復雜度遠遠跑不滿,因為對于多數數據 m m m 很小,會限制枚舉的狀態數量)

三、代碼

#include <bits/stdc++.h>using namespace std;const int maxn = 2e3 + 7;
const int maxv = 3e2 + 7;
const int inf  = 0x3f3f3f3f;int n, m, v, e;
int c[maxn], d[maxn];
double p[maxn];
int dis[maxv][maxv];
void Floyd() {for (int k = 1; k <= v; ++k)for (int i = 1; i <= v; ++i)for (int j = 1; j <= v; ++j)dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}
double ans;
int main() {scanf("%d%d%d%d", &n, &m, &v, &e);for (int i = 1; i <= n; ++i) scanf("%d", c + i);for (int i = 1; i <= n; ++i) scanf("%d", d + i);for (int i = 1; i <= n; ++i) scanf("%lf", p + i);memset(dis, inf, sizeof(dis));for (int i = 1; i <= v; ++i) dis[i][i] = dis[0][i] = dis[i][0] = 0;for (int i = 1, a, b, w; i <= e; ++i) {scanf("%d%d%d", &a, &b, &w);dis[a][b] = dis[b][a] = min(w, dis[a][b]);}Floyd();if (m == 0) {for (int i = 1; i < n; ++i)ans += dis[c[i]][c[i + 1]];printf("%.2lf\n", ans);return 0;}ans = 2e9;for (int s = 0; s < (1 << n); ++s) {  // 枚舉【申請情況】if (__builtin_popcount(s) > m) continue;  // 用來計算 s 二進制中有多少個 1 的函數double sum = 0;  // 此【申請情況】下的期望for (int ss = s; 1; ss = s & (ss - 1)) {  // 枚舉【同意情況】double tmp = 0;  // 此【同意情況】對【申請情況】的貢獻for (int i = 2; i <= n; ++i) {int lst = ((ss & (1 << (i - 1 - 1))) ? d[i - 1] : c[i - 1]);int now = ((ss & (1 << (i - 1))) ? d[i] : c[i]);tmp += dis[lst][now];}for (int i = 1; i <= n; ++i)if (ss & (1 << (i - 1))) tmp *= p[i];else if (s & (1 << (i - 1))) tmp *= 1 - p[i];sum += tmp;if (ss == 0) break;}ans = min(ans, sum);}printf("%.2lf\n", ans);return 0;
} 

期望得分 68 p t s 68pts 68pts,實際得分 68 p t s 68pts 68pts
(洛谷測評機跑出來挺迷的,應該是數據水的問題,前面暴力的數據點一部分沒過,后面正解的數據點過了一部分)


正解

概率期望的題一般就是拿 d p dp dp 做。

一、思路

狀態設計

  • 很明顯要有兩維的狀態 i , j i, j i,j,表示前 i i i 個中選了 j j j 個。
    但是由于花費還與上一狀態有關(上一個課程是在 c i c_i ci? 還是 d i d_i di?),所以還要一維表示這個課是否被申請了。
  • d p i , j , 0 / 1 dp_{i, j, 0/1} dpi,j,0/1? 表示在前 i i i 個課中 申請了(注意不是同意!!) j j j 個,且第 i i i 個課【沒被申請 / 被申請了】時的最小期望。

狀態轉移

  1. 若當前課程 i i i 不申請,且上一個課程也沒有申請,那么轉移方程為: d p i , j , 0 = m i n ( d p i , j , d p i ? 1 , j , 0 + d i s c i ? 1 , c i ) dp_{i, j, 0} = min(dp_{i, j}, dp_{i - 1, j, 0} + dis_{c_{i - 1}, c_i}) dpi,j,0?=min(dpi,j?,dpi?1,j,0?+disci?1?,ci??)
  2. 若當前課程 i i i 不申請,但上一個課程申請了,那么轉移方程為(轉移條件為 j > 0 j > 0 j>0): d p i , j , 0 = m i n ( d p i , j , 0 , d p i ? 1 , j , 1 + d i s c i ? 1 , c i × ( 1 ? k i ) + d i s d i ? 1 , c i × k i ) dp_{i, j, 0} = min( dp_{i, j, 0}, dp_{i - 1, j, 1} + dis_{c_{i - 1}, c_{i}} \times (1 - k_i) + dis_{d_{i - 1}, c_i} \times k_{i}) dpi,j,0?=min(dpi,j,0?,dpi?1,j,1?+disci?1?,ci??×(1?ki?)+disdi?1?,ci??×ki?)后面的分別對應【上一次申請沒通過】和【上一次申請通過了】;
  3. 若當前課程 i i i 申請,那么上一次可以申請,也可以不申請,總共有四種情況,在此就不列舉出來了(條件當然也是 j > 0 j > 0 j>0)。

邊界條件

  • 只有一個課程時,申請或不申請期望花費都為 0 0 0,即: d p 1 , 0 , 0 = d p 1 , 1 , 1 = 0 dp_{1,0,0} = dp_{1,1,1} = 0 dp1,0,0?=dp1,1,1?=0
  • 而對于 d p 1 , 0 , 1 , d p 1 , 1 , 0 dp_{1,0,1},dp_{1,1,0} dp1,0,1?,dp1,1,0? 這種不合法狀態,我們可以先把他們設為正無窮,這樣就不會從它門轉移了。

答案

  • 因為題目說可以不用玩 m m m 次申請,所以答案就是 m i n i = 0 m { d p n , i , 0 , d p n , i , 1 } min_{i = 0}^{m} \left\{dp_{n, i,0}, dp_{n, i, 1} \right\} mini=0m?{dpn,i,0?,dpn,i,1?}

復雜度

  1. 空間: O ( v 2 + n × m ) O(v^2 + n \times m) O(v2+n×m)
  2. 時間: O ( v 3 + n × m ) O(v^3 + n \times m) O(v3+n×m)

二、代碼

#include <bits/stdc++.h>using namespace std;const int maxn = 2e3 + 7;
const int maxv = 3e2 + 7;
const int inf  = 0x3f3f3f3f;int n, m, v, e;
int c[maxn], d[maxn];
double p[maxn];
int dis[maxv][maxv];
void Floyd() {for (int k = 1; k <= v; ++k)for (int i = 1; i <= v; ++i)for (int j = 1; j <= v; ++j)dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}double dp[maxn][maxn][2];
double ans;
int main() {scanf("%d%d%d%d", &n, &m, &v, &e);for (int i = 1; i <= n; ++i) scanf("%d", c + i);for (int i = 1; i <= n; ++i) scanf("%d", d + i);for (int i = 1; i <= n; ++i) scanf("%lf", p + i);memset(dis, 63, sizeof(dis));for (int i = 1; i <= v; ++i) dis[i][i] = dis[i][0] = dis[0][i] = 0;for (int i = 1, a, b, w; i <= e; ++i) {scanf("%d%d%d", &a, &b, &w);dis[a][b] = dis[b][a] = min(w, dis[a][b]);}Floyd();for (int i = 0; i <= n; ++i)for (int j = 0; j <= m; ++j)dp[i][j][0] = dp[i][j][1] = 2e9;dp[1][0][0] = dp[1][1][1] = 0;for (int i = 2; i <= n; ++i) {dp[i][0][0] = dp[i - 1][0][0] + dis[c[i - 1]][c[i]];for (int j = 1; j <= min(i, m); ++j) {// 巨丑馬蜂dp[i][j][0] = min(dp[i - 1][j][0] + dis[c[i - 1]][c[i]],dp[i - 1][j][1] + dis[c[i - 1]][c[i]] * (1 - p[i - 1]) + dis[d[i - 1]][c[i]] * p[i - 1]);dp[i][j][1] = min(dp[i][j][1], dp[i - 1][j - 1][0] + dis[c[i - 1]][c[i]] * (1 - p[i]) + dis[c[i - 1]][d[i]] * p[i]);dp[i][j][1] = min(dp[i][j][1], dp[i - 1][j - 1][1] + dis[c[i - 1]][c[i]] * (1 - p[i - 1]) * (1 - p[i]) + dis[c[i - 1]][d[i]] * (1 - p[i - 1]) * p[i] + dis[d[i - 1]][c[i]] * p[i - 1] * (1 - p[i]) + dis[d[i - 1]][d[i]] * p[i - 1] * p[i]);}}ans = 2e9;for (int i = 0; i <= m; ++i)ans = min(ans, min(dp[n][i][0], dp[n][i][1]));printf("%.2lf\n", ans);return 0;
} 

期望的分 100 p t s 100pts 100pts,實際得分 100 p t s 100pts 100pts

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/904025.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/904025.shtml
英文地址,請注明出處:http://en.pswp.cn/news/904025.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于Springboot+Vue3.0的前后端分離的個人旅游足跡可視化平臺

文章目錄 0、前言1、前端開發1.1 登錄注冊頁面1.2 首頁1.3 足跡管理1.3.1 足跡列表1.3.2 添加足跡1.4 個人中心1.4.1 足跡成就1.4.2 個人信息1.4.3 我的計劃2、后端開發2.1 用戶接口開發2.2 足跡點接口2.3 旅游計劃接口3、完整代碼資料下載0、前言 項目亮點: 前端用戶權限動態…

大數據應用開發與實戰(1)

一、Matplotlib 基礎認知 功能特性&#xff1a;是 Python 強大的繪圖庫&#xff0c;能將數據以多樣化的圖表形式呈現&#xff0c;涵蓋靜態、動態和交互式圖表&#xff0c;支持多種輸出格式&#xff0c;滿足不同場景下的數據可視化需求。 二Matplotlib Pyplott 函數繪圖技巧&a…

神經網絡的基本概念與深度解析——基于生物機制的仿生建模與工程實現

廣義上講&#xff0c;神經網絡是泛指生物神經網絡與人工神經網絡這兩個方面。所謂生物神經網絡是指由中樞神經系統&#xff08;腦和脊髓&#xff09;及周圍神經系統&#xff08;感覺神經、運動神經、交感神經、副交感神經等&#xff09;所構成的錯綜復雜的神經網絡&#xff0c;…

Linux53 百度網盤運行(下載devtoolset11后仍提示stdc++3.0.29缺失 計劃用docker容器隔離運行,計劃后續再看)

算了 放棄 都用到docker了 計劃先看看系統服務后續再研究吧 百度網盤運行(下載devtoolset11后仍提示stdc3.0.29缺失 計劃用docker容器隔離運行 但是由于系統服務未扎實&#xff0c;計劃后續再看 重新下了el7的版本 剛才已啟動成功 單輸入xlock不啟動 切換用戶也不啟動 …

高維亞空間超頻物質變壓縮技術 第27次CCF-CSP計算機軟件能力認證

很經典的dp問題&#xff1a; 設dp數組為f[i]前i個黃金的最小成本 遞推公式就是遍歷之前0-j的dp[j] 再加上后面這一段的成本取min 而計算后面的成本需要段體積 使用前綴和儲存體積即可 注意題目限制條件每段最大m需要遞增 所以遇到某些問題需要continue 每段內編號最大的黃…

里氏替換原則(LSP)

太好了&#xff0c;現在我們來講解 SOLID 中非常核心的 LSP&#xff1a;里氏替換原則&#xff08;Liskov Substitution Principle&#xff09;。 我會一步步講清楚&#xff1a; 什么是 LSP&#xff1f;為什么重要&#xff1f;優劣分析Python 正反例子清晰的結構圖&#xff08…

skynet.socket.limit 使用詳解

目錄 核心作用方法定義使用場景場景 1&#xff1a;限制接收緩沖區&#xff08;防御大包攻擊&#xff09;場景 2&#xff1a;動態調整限制&#xff08;應對不同負載&#xff09; 底層機制注意事項完整示例&#xff1a;帶流量控制的 Echo 服務總結 在 Skynet 框架中&#xff0c;s…

算法每日一題 | 入門-順序結構-數字反轉

數字反轉 題目描述 輸入一個不小于 且小于 &#xff0c;同時包括小數點后一位的一個浮點數&#xff0c;例如 &#xff0c;要求把這個數字翻轉過來&#xff0c;變成 并輸出。 輸入格式 一行一個浮點數 輸出格式 一行一個浮點數 輸入輸出樣例 #1 輸入 #1 123.4輸出 #1 …

數據庫數據去重常用方式

數據庫數據去重是一個常見的操作&#xff0c;常用的方式包擇包括&#xff1a; 使用 DISTINCT 關鍵字&#xff1a;在查詢數據時&#xff0c;可以使用 SELECT DISTINCT 來去除結果集中的重復數據。 使用 GROUP BY 語句&#xff1a;可以使用 GROUP BY 子句來對結果進行分組&#…

快樂數(簡單)

代碼&#xff1a; import java.util.HashSet; import java.util.Set;class Solution {public boolean isHappy(int n) {Set<Integer> seen new HashSet<>();while (n ! 1 && !seen.contains(n)) {seen.add(n);n getNext(n);}return n 1;}private int g…

Linux操作系統從入門到實戰(五)詳細講解Linux權限概念

Linux操作系統從入門到實戰&#xff08;五&#xff09;詳細講解Linux權限概念 前言一、Linux中兩種用戶1.1 超級用戶&#xff08;root&#xff09;1.2 普通用戶1.3 切換用戶命令 二、Linux權限管理2.1 文件訪問者的分類&#xff1a;誰能訪問文件&#xff1f;2.2 文件類型2.3 基…

91.首次使用Maui的體驗與建議 C#例子 Maui例子

最近我開始接觸Maui&#xff0c;記錄一下我的首次使用體驗&#xff0c;希望能給大家提供一些參考。 安裝與創建項目 首次接觸Maui&#xff0c;其實遇到了不少疑惑。首先&#xff0c;通過Visual Studio的安裝器安裝Maui開發環境。安裝過程還算順利&#xff0c;但需要注意的是&…

【家政平臺開發(100)】終結篇,破局·拓新:家政平臺未來發展的戰略藍圖

本【家政平臺開發】專欄聚焦家政平臺從 0 到 1 的全流程打造。從前期需求分析,剖析家政行業現狀、挖掘用戶需求與梳理功能要點,到系統設計階段的架構選型、數據庫構建,再到開發階段各模塊逐一實現。涵蓋移動與 PC 端設計、接口開發及性能優化,測試階段多維度保障平臺質量,…

小程序滾動條隱藏(uniapp版本)

單獨指定頁面隱藏&#xff08;找到對應的scroll-view&#xff09; <style> /* 全局隱藏滾動條樣式 */ ::-webkit-scrollbar { display: none; width: 0; height: 0; color: transparent; background: transparent; } /* 確保scroll-view組件也隱藏滾動條 */ …

5月3日日記

上午睡到自然醒&#xff08;其實六點多被我爸叫起來搶火車票&#xff0c;發現明天中午的軟臥候補上了&#xff0c;挺好的&#xff09;然后繼續睡到快10點。 中午吃的什么來著&#xff0c;好像是西紅柿炒雞蛋和藜麥飯&#xff0c;有個魚不是很想吃就沒吃 中午打了兩把吃雞&…

【Spring】Spring中8種常見依賴注入使用示例

在 Spring 中&#xff0c;IoC 注入可以通過多種方式實現&#xff0c;涵蓋不同場景的依賴管理。以下是 8 種常見場景的詳細示例及說明&#xff0c;結合 XML、注解和 Java 配置類三種方式。 1. 構造器注入&#xff08;推薦方式&#xff09; 通過構造器傳遞依賴&#xff0c;確保對…

藍橋杯 擺動序列

擺動序列 原題目鏈接 題目描述 如果一個序列的奇數項都比前一項大&#xff0c;偶數項都比前一項小&#xff0c;則稱為一個擺動序列。 即對于任意整數 i&#xff08;i ≥ 1&#xff09;滿足&#xff1a; a?? < a????&#xff0c;a???? > a?? 小明想知道&…

REINFORCE蒙特卡羅策略梯度算法詳解:python從零實現

&#x1f9e0; 向所有學習者致敬&#xff01; “學習不是裝滿一桶水&#xff0c;而是點燃一把火。” —— 葉芝 我的博客主頁&#xff1a; https://lizheng.blog.csdn.net &#x1f310; 歡迎點擊加入AI人工智能社區&#xff01; &#x1f680; 讓我們一起努力&#xff0c;共創…

深入了解Linux系統—— 操作系統

一、馮諾依曼體系結構 現在我們常見的計算機&#xff08;筆記本電腦等&#xff09;和不常見的計算機&#xff08;服務器&#xff09;它們都滿足馮諾依曼體系。 我們可以把計算機理解成一個個硬件組成的 輸入設備&#xff1a;鍵盤、鼠標、攝像頭、網卡、磁盤等輸出設備&#xf…

RPG7.準備GAS的工作

1.啟動項目&#xff0c;為項目添加gameplayability插件 2.添加abilitysystemcomponent的c類 3.添加attributeset的c類 4.往build.cs內添加模塊 5.進入CharacterBase內&#xff0c;添加gameplayasystem和attributbeset&#xff0c;覆寫PossessedBy()和GetAbilitysystemcomponent…