日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

信息学奥赛一本通 1319:【例6.1】排队接水 | 洛谷 P1223 排队接水

發(fā)布時間:2025/3/17 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 信息学奥赛一本通 1319:【例6.1】排队接水 | 洛谷 P1223 排队接水 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

【題目鏈接】

ybt 1319:【例6.1】排隊接水
洛谷 P1223 排隊接水

【題目考點】

1. 貪心

2. 貪心選擇性質(zhì)的證明

要想證明貪心選擇可以得到最優(yōu)解,只需要證明最優(yōu)解包含每一次的貪心選擇。
使用數(shù)學(xué)歸納法:

  • 證明最優(yōu)解包含第一次的貪心選擇
  • 假設(shè)存在最優(yōu)解包含前k次的貪心選擇,證明該最優(yōu)解包含第k+1次的貪心選擇
  • 【解題思路】

    1. 證明貪心選擇性質(zhì)

    貪心選擇:每次選擇接水時間最短的人去接水
    貪心選擇性質(zhì)的證明:
    設(shè)n個人的編號為1,2,3,…,n

  • 證明:存在最優(yōu)解,第一個接水的人是通過貪心選擇得到的。
    接水時長最短的人編號為ggg,其接水時間為TgT_gTg?
  • 使用反證法:假設(shè)對于所有最優(yōu)解,第一個接水的人都不可以是貪心選擇得到的人g。
    則對于某種最優(yōu)解,其接水順序為d1,d2,...,dnd_1,d_2,...,d_nd1?,d2?,...,dn?,假設(shè)g是第m個接水的人,即dm=g(m>1)d_m = g (m > 1)dm?=g(m>1),記第1個接水的人的編號為a,即d1=ad_1 = ad1?=a
    由于g的所有人中打水時間最短的人,那么一定有Ta>TgT_{a} > T_{g}Ta?>Tg?
    如果交換aaaggg,考慮總接水時間的變化:

    • d2~dm?1d_2\sim d_{m-1}d2?dm?1?一共m?2m-2m?2個人,每人等待的時間減少了TaT_aTa?增加了TgT_gTg?,總減少時間為(m?2)(Ta?Tg)(m-2)(T_a-T_g)(m?2)(Ta??Tg?)
    • g等待的時間從Ta+∑i=2m?1TdiT_a+\sum_{i=2}^{m-1}T_{di}Ta?+i=2m?1?Tdi?變?yōu)?span id="ozvdkddzhkzd" class="katex--inline">000,等待時間減少Ta+∑i=2m?1TdiT_a+\sum_{i=2}^{m-1}T_{di}Ta?+i=2m?1?Tdi?
    • a的等待時間從000變?yōu)?span id="ozvdkddzhkzd" class="katex--inline">Tg+∑i=2m?1TdiT_g+\sum_{i=2}^{m-1}T_{di}Tg?+i=2m?1?Tdi?,等待時間減少?(Tg+∑i=2m?1Tdi)-(T_g+\sum_{i=2}^{m-1}T_{di})?(Tg?+i=2m?1?Tdi?)
    • 總減少的等待時間為上面三者的加和,結(jié)果為(m?1)(Ta?Tg)(m-1)(T_a-T_g)(m?1)(Ta??Tg?)。由于m>1m>1m>1Ta>TbT_a>T_bTa?>Tb?,那么(m?1)(Ta?Tg)>0(m-1)(T_a-T_g) > 0(m?1)(Ta??Tg?)>0

    因此,如果交換a與g,總接水時間會減少。這與當(dāng)前解是可以使平均接水時間最小的最優(yōu)解相矛盾,因而原命題得證。

  • 證明:存在最優(yōu)解,假設(shè)前k個人接水的人都是通過貪心選擇得到的,第k+1個接水的人也通過貪心選擇得到,即選擇剩下的接水時長最短的人。
  • 證明方法與上面第1點的證明方法類似,把證明中的“第一個接水的人”改為“第k+1個接水的人”即可,不再贅述。

    以上證明了該問題具有貪心選擇性質(zhì),即每次選擇接水時間最短的人去接水,可以使n個人的平均等待時間最小。

    2. 具體做法

    結(jié)構(gòu)體中保存人的編號和打水時間,按打水時間升序?qū)Y(jié)構(gòu)體對象進行排序。計算所有人的等待時間加和,最后除以總?cè)藬?shù)。

    3. 排序方法

    該題說當(dāng)時間重復(fù)時,按照輸入順序輸出。雖然它說“用sort是可以的”,但嚴(yán)格來講,這里按照輸入順序?qū)⑵浼尤霐?shù)組中,而后按照打水時間進行排序。如要讓相同打水時間的元素保持輸入時的先后順序,則理論上必須選用穩(wěn)定的排序算法。所以這里我們使用stable_sort進行排序。

    【題解代碼】

    解法1:貪心,使用stable_sort進行排序

    #include<bits/stdc++.h> using namespace std; #define N 1005 struct Time {double t;int i;//t:時間 i:人的編號 }; Time a[N]; bool cmp(const Time &a, const Time &b) {return a.t < b.t; } int main() {int n;double sumTime = 0, waitTime = 0;cin >> n;for(int i = 1; i <= n; ++i){cin >> a[i].t;a[i].i = i;}stable_sort(a+1, a+1+n, cmp);for(int i = 1; i <= n; ++i){sumTime += waitTime;//waitTime:當(dāng)前這個人已經(jīng)等的時間 waitTime += a[i].t;cout << a[i].i << ' ';}cout << endl << fixed << setprecision(2) << sumTime / n; return 0; }

    解法2:貪心 手寫歸并排序

    #include<bits/stdc++.h> using namespace std; #define N 1005 struct Time {double t;int i;//t:時間 i:第幾個 }; Time a[N], t[N]; void mergeSort(int l, int r)//歸并排序 {if(l >= r)return;int mid = (l+r)/2;mergeSort(l, mid);mergeSort(mid+1, r);int i = l, j = mid+1, ti = l;while(i <= mid && j <= r){if(a[i].t < a[j].t)t[ti++] = a[i++];elset[ti++] = a[j++];}while(i <= mid)t[ti++] = a[i++];while(j <= r)t[ti++] = a[j++];for(int k = l; k <= r; ++k)a[k] = t[k]; } int main() {int n;double sumTime = 0, waitTime = 0;cin >> n;for(int i = 1; i <= n; ++i){cin >> a[i].t;a[i].i = i;}mergeSort(1, n);for(int i = 1; i <= n; ++i){sumTime += waitTime;//waitTime:當(dāng)前這個人已經(jīng)等的時間 waitTime += a[i].t;cout << a[i].i << ' ';}cout << endl << fixed << setprecision(2) << sumTime / n; return 0; }

    總結(jié)

    以上是生活随笔為你收集整理的信息学奥赛一本通 1319:【例6.1】排队接水 | 洛谷 P1223 排队接水的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。