洛谷-题解 P2672 【推销员】
生活随笔
收集整理的這篇文章主要介紹了
洛谷-题解 P2672 【推销员】
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
獨門思路!鏈表加優(yōu)先隊列!
這題一望,貪心是跑不掉了,但是我貪心并不好,所以想到了一個復(fù)雜一些但思路更保穩(wěn)的做法
思路:
1 因為是離線操作,所以我們可以倒著求,先求x=n的情況,因為那樣直接就知道了
2 用優(yōu)先隊列維護每個住戶對疲勞度的貢獻,維護最小的,因為x=i的疲勞度減去此時減去對疲勞度貢獻最小的用戶當(dāng)然為x=i-1的疲勞度的最大值
3 需要用鏈表,因為當(dāng)某個用戶自己本身距離最遠或比自己距離遠且相鄰的用戶距離最遠,那么刪去這個用戶,其他兩個用戶對疲勞度貢獻分別更新(往返距離變化了)
4 一些小的細節(jié),保證正確,因為優(yōu)先隊列里會有一些無用的用戶
下面是可以簡化和優(yōu)化的代碼,供參考思路
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define re register int 10 inline int read(){ 11 int x=0,ff=1;char c=getchar(); 12 while(c<'0'||c>'9'){if(c=='-')ff=-1;c=getchar();} 13 while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();} 14 return x*ff; 15 } 16 struct book{ 17 int x,i,b; 18 bool friend operator <(book xx,book yy){ 19 return xx.x>yy.x; 20 } 21 //重載運算 22 }; 23 priority_queue<book>dl; 24 int a[100005],c[100005],tot[100005]; 25 //a和c是距離和疲勞度,tot記錄答案 26 int lb[100005],to[100005],s,tt[100005]; 27 //lb是前驅(qū),rb是后驅(qū)(鏈表)tt表示此時對i用戶距離修改次數(shù),與book中的b對應(yīng) 28 bool v[100005],tl[100005]; 29 //v表示次用戶是否刪過(其實可以省略)tl表示此點是否為最遠距離 30 int main(){ 31 int n=read(),t;t=n; 32 for(int i=1;i<=n;i++){ 33 a[i]=read(); 34 } 35 for(int i=1;i<n;i++){ 36 c[i]=read();lb[i]=i-1;to[i]=i+1; 37 dl.push((book){c[i],i,0});s+=c[i]; 38 //入隊,并求出x=n的疲勞度,維護鏈表 39 } 40 c[n]=read();lb[n]=n-1;s+=c[n]+a[n]*2; 41 dl.push((book){c[n]+(a[n]-a[n-1])*2,n,1}); 42 //初始化,與下面入隊思路類似 43 tt[n]=1;tl[n]=1; 44 while(t){ 45 if(dl.empty())break; 46 tot[t]=s; 47 book y=dl.top();dl.pop(); 48 if(y.b<tt[y.i])continue; 49 //判斷此用戶是否為最新狀態(tài) 50 if(v[y.i])continue; 51 v[y.i]=1; 52 //是否已刪去 53 t--; 54 to[lb[y.i]]=to[y.i]; 55 lb[to[y.i]]=lb[y.i]; 56 //更新鏈表 57 s-=y.x;//更新疲勞度 58 //下面是關(guān)于前驅(qū)和后繼的兩種特殊情況 59 if(y.b){ 60 if(lb[y.i]==0)break;tt[lb[y.i]]++; 61 dl.push((book){c[lb[y.i]]+2*(a[lb[y.i]]-a[lb[lb[y.i]]]),lb[y.i],tt[lb[y.i]]}); 62 //特殊入隊,表示此用戶成為最遠的,要更新刪去此點的代價,注意,是往返 63 //其他入隊于此類似 64 } 65 if(tl[to[y.i]]){ 66 tt[to[y.i]]++; 67 dl.push((book){c[to[y.i]]+2*(a[to[y.i]]-a[lb[y.i]]),to[y.i],tt[to[y.i]]}); 68 } 69 } 70 for(int i=1;i<=n;i++){ 71 printf("%d\n",tot[i]); 72 //輸出,此程序是離線做的 73 } 74 return 0; 75 }
洛谷上第39篇題解,這樣管理員都給過可見我思路有多神奇
洛谷博客求贊
轉(zhuǎn)載于:https://www.cnblogs.com/ffrxy01bt/p/11099707.html
總結(jié)
以上是生活随笔為你收集整理的洛谷-题解 P2672 【推销员】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 吴恩达Drive.ai因经营困难“卖身”
- 下一篇: Docker基本命令汇总