国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

sgu148 B-station(Bomb)

2019-11-14 12:00:53
字體:
來源:轉載
供稿:網友

題目

        在離著名的國家Berland不遠的地方,有一個水下工作站。這個工作站有N層。已知:是第層裝有Wi的水,最多可以容納Li的水,恐怖分子炸毀第i的代價是Pi。第i層一旦被炸毀,該層所有的水都將傾瀉到第i+1層。如果某一層的水量超過了它的容量(即Li),那么該層就將自動被毀壞,所有的水也會傾瀉到下一層。

        Pivland的恐怖分子想要用最少的錢毀掉第N層,現在他雇傭你來計算,需要炸毀哪些層。

 

 

輸入

 

      第一行有一個自然數N(1<=n<=15000)。接下來的N行,每行3個整數Wi, Li, Pi(0<=Wi,Li,Pi<=15000)。

 

輸出

 

     輸出需要炸毀的層的編號。

Solution1:小根堆+枚舉。

從下往上推的話,f[i]是從i層開始炸毀的代價如果炸毀i-1,且s[i]-s[i-2]>l[i],那么從第i-1層開始炸毀的代價是f[i]+c[i-1]-c[i]; 從第k層開始炸毀時只要將第i(k<i<=n)層里(s[i]-s[k-1]>l[i]) 層里之前算作炸毀的層的c[i]減去,并標記沒被炸毀.用優先隊列優化的話將快很多,只要將當前炸毀的層入隊,當滿足s[i]-s[k-1]>l[i]時,出隊并減去c[i];

#include <cstdio>  #include <queue>  #include <utility>  using namespace std;  typedef pair<int,int> aii;const int maxx = 15000+10, INF = 2e9;  PRiority_queue< aii > heap;int n;int ans = INF,flag = 0,sum = 0,Sum = 0; int v[maxx],s[maxx],c[maxx];int pre[maxx];bool hash[maxx];int main()   {  //	freopen("Bstation.in","r",stdin);//	freopen("Bstation.out","w",stdout);	    scanf("%d",&n);      	for(int i=n;i>=1;i--)       {          scanf("%d%d%d",&s[i],&v[i],&c[i]);            pre[i] = pre[i+1]+s[i];      }       	for(int i=1;i<=n;i++)      {          for(;!heap.empty() && heap.top().first>pre[i+1]; heap.pop())              sum -= heap.top().second;        heap.push(make_pair(pre[i]-v[i], c[i]));          sum+=c[i];          if(ans>sum)          {              ans = sum;              flag = i;             }      }        	for(int i=flag;i>=1;i--)      {          Sum += s[i];        if(Sum>v[i])              hash[i] = true;       }          for(int i=flag;i>=1;i--)          if(!hash[i])              printf("%d/n", n-i+1);      return 0;  }Solution2:類似二分查找的算法。

之前做過B-station,是用堆的方法。奈何考場碰到此題時早已把此方法忘得一干二凈/捂臉。所以迫不得已,強行自己創造了

一個類似二分查找的方法來通過此題防止爆零…咳咳咳,這個方法大致是這樣的。讀入時首先處理(由于本人個人習慣原因,把最高

層叫做第一層。要炸的叫最底層)之后用sum[i]表示重量的前綴和,用val[i]表示炸該層的費用。之后把每層放入結構體。關鍵字:

d,l,w,id,need(need保存的是壓毀此層時至少毀掉的最高層。換句話說,設i層的need為need[i],只要從need[i]到i-1之間

所有層都已毀壞,第i層就會直接被壓毀。而這個need怎么求呢?假設第i層的need[i]為T,則有sum[i]-sum[T-1]>l[i]。經變形得

到sum[T-1]<sum[i]-l[i]。這時候,因為sum單調遞增,可知sum[T]>=sum[i]-l[i]。所以可以用lower_bound函數直接找出

need[i]。接下來我們要做的是將結構體依照need進行排序。然后創建一個vector<int> sale[]的數組。sale[i]中存以此層作為最

高層時可以壓毀的層的編號。之后就直接自底往上開始枚舉最高層。每次枚舉時首先tmp += val[i](都考慮直接炸掉),之后在

sale[i]中進行查找,如果有編號在i層和底層之間,也就是sale[i][j]>i,則tmp-=val[sale[i][j]]。(說明以i為最高層時此層不用

炸)。每次枚舉過后比較tmp與Ans。最終就能得到答案。//考試時做了幾個小時,生無可戀.jpg。

#include <cstdio>#include <algorithm>#include <queue>#include <vector>using namespace std;const int maxx = 100000 + 100;struct Edge{    int id;    int d;    int l;    int w;    int need;}Edges[maxx];long long sum[maxx],val[maxx],cost[maxx];long long Ans = 1e9 + 100,tmp;int n;vector <int> sale[maxx];bool cmp(Edge a,Edge b){    if(a.need != b.need)    return a.need<b.need;    else    return a.id<b.id;}int main(){//    freopen("Bomb.in","r",stdin);//    freopen("Bomb.out","w",stdout);        scanf("%d",&n);        for(int i=n;i>=1;i--){        scanf("%d%d%d",&Edges[i].d,&Edges[i].w,&Edges[i].l);        val[i]=Edges[i].d;        Edges[i].id = i;    }        for(int i=1;i<=n;i++)        sum[i]=sum[i-1]+Edges[i].w;        for(int i=1;i<=n;i++){        int T = lower_bound(sum,sum+i,sum[i]-Edges[i].l)-sum;        if(T>0) Edges[i].need = T;        else Edges[i].need = 0;    }        sort(Edges+1,Edges+n+1,cmp);        for(int i=1;i<=n;i++)        sale[Edges[i].need].push_back(Edges[i].id);        for(int i=n;i>=1;i--){        tmp += val[i];        for(int j=0;j<sale[i].size();j++){            if(sale[i][j]>i)            tmp -= val[sale[i][j]];        }        Ans = min(Ans,tmp);    }    printf("%d",Ans);    return 0;}看來做過的題目還是要好好學懂啊QvQ。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 平顶山市| 衢州市| 兰州市| 电白县| 新田县| 佛冈县| 沈丘县| 汉沽区| 通辽市| 西盟| 北流市| 四川省| 宁河县| 马公市| 固始县| 黄大仙区| 辽源市| 泽库县| 陇川县| 衡阳县| 大英县| 河北区| 和田县| 旬阳县| 永新县| 南开区| 丹寨县| 石狮市| 思南县| 绵竹市| 自治县| 牙克石市| 敦化市| 巫溪县| 定边县| 体育| 宝清县| 三穗县| 甘孜| 皋兰县| 滁州市|