當(dāng)前位置:
首頁(yè) >
POJ1018贪心(多路归并的想法)
發(fā)布時(shí)間:2025/6/17
29
豆豆
生活随笔
收集整理的這篇文章主要介紹了
POJ1018贪心(多路归并的想法)
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
題意:
? ? ?有n個(gè)服務(wù)器,每個(gè)服務(wù)器都要安裝網(wǎng)線(必須也只能安裝一個(gè)),然后每個(gè)服務(wù)器都有mi種選擇網(wǎng)線的方式,每種方式兩個(gè)參數(shù),一個(gè)是速度b,另一個(gè)是價(jià)錢(qián)p,然后讓你找到一個(gè)最大的比值 minb/sump,就是所有的選擇中最小的那個(gè)速度,必上話的錢(qián)的總和。
思路:?
? ? ? 這個(gè)題目按照討論組里面的說(shuō)法估計(jì)做法很多,不管了,說(shuō)下我自己的做法吧,我的做法有點(diǎn)像操作系統(tǒng)里面那個(gè)多路歸并(如果沒(méi)記錯(cuò)是叫這個(gè),做題的時(shí)候突然想到這個(gè)方式,試了下,還真行),具體是這樣,枚舉最小的b,也就是最小的那個(gè)帶寬,對(duì)于每個(gè)服務(wù)器,我們可以先把他所有的可選擇項(xiàng)都按照帶寬從小到大排序,排序后再倒著預(yù)處理得到每個(gè)選項(xiàng)后面中最小的那個(gè)花費(fèi),全部這樣處理完之后就得到了一個(gè)二維的表,然后我們開(kāi)始枚舉,每個(gè)表都是根據(jù)帶寬從小到大排序的,這樣所有中最小的那個(gè)肯定就是某一個(gè)的第一項(xiàng),我們O(n)的時(shí)間找到第一項(xiàng),以這一項(xiàng)的帶寬為最小帶寬,花費(fèi)是當(dāng)前這個(gè)選項(xiàng)的花費(fèi),其他的就選最小的花費(fèi),然后刪除找到的這一項(xiàng),就這樣一直找到頭一個(gè)服務(wù)器的選項(xiàng)全都用完了位置,還有就是刪除項(xiàng)的時(shí)候可以開(kāi)一個(gè)一維數(shù)組,記錄當(dāng)前這個(gè)服務(wù)器已經(jīng)用到第幾項(xiàng)了,刪除第i個(gè)服務(wù)器的當(dāng)前項(xiàng),直接mk[i]++就行了,16msAC,總的時(shí)間復(fù)雜度最壞應(yīng)該是 O(n*n*n) 1000000吧。感覺(jué)思路有點(diǎn)瞎扯了,呵呵,題目不難,瞎扯就瞎扯吧,好就說(shuō)這些。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 100 + 10
#define INF 1000000000
using namespace std;
typedef struct
{
? ? int b ,p ,minp;
}NODE;
NODE node[N][N];
int now[N] ,num[N];
bool camp(NODE a ,NODE b)
{
? ? return a.b < b.b;
}
int main ()
{
? ? int t ,i ,j ,n ,tmp ,sn;
? ? scanf("%d" ,&t);
? ? while(t--)
? ? {
? ? ? ? scanf("%d" ,&n);
? ? ? ? for(i = 1 ,sn = 0 ;i <= n ;i ++)
? ? ? ? {
? ? ? ? ? ? scanf("%d" ,&num[i]);
? ? ? ? ? ? sn += num[i];
? ? ? ? ? ? for(j = 1 ;j <= num[i] ;j ++)
? ? ? ? ? ? scanf("%d %d" ,&node[i][j].b ,&node[i][j].p);
? ? ? ? ? ? sort(node[i] + 1 ,node[i] + num[i] + 1 ,camp);
? ? ? ? ? ? for(j = num[i] ;j >= 1 ;j --)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if(j == num[i] || tmp > node[i][j].p)
? ? ? ? ? ? ? ? tmp = node[i][j].p;
? ? ? ? ? ? ? ? node[i][j].minp = tmp;
? ? ? ? ? ? }
? ? ? ? ? ? now[i] = 1;
? ? ? ? }
? ? ? ? double Ans = 0;
? ? ? ? int nowb ,nowp;
? ? ? ? while(sn--)
? ? ? ? {
? ? ? ? ? ? nowb = INF;
? ? ? ? ? ? nowp = 0;
? ? ? ? ? ? int mkbreak = 0;
? ? ? ? ? ? for(i = 1 ;i <= n ;i ++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if(now[i] > num[i]) mkbreak = 1;
? ? ? ? ? ? ? ? if(nowb > node[i][now[i]].b)
? ? ? ? ? ? ? ? nowb = node[i][now[i]].b;
? ? ? ? ? ? }
? ? ? ? ? ? if(mkbreak) break;
? ? ? ? ? ? int mk = 0;
? ? ? ? ? ? for(i = 1 ;i <= n ;i ++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? //if(now[i] > num[i]) continue;
? ? ? ? ? ? ? ? if(!mk && nowb == node[i][now[i]].b)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? mk = 1;
? ? ? ? ? ? ? ? ? ? nowp += node[i][now[i]].p;
? ? ? ? ? ? ? ? ? ? now[i] ++;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? else nowp += node[i][now[i]].minp;
? ? ? ? ? ? }
? ? ? ? ? ? if(Ans < nowb * 1.0 / nowp)
? ? ? ? ? ? Ans = nowb * 1.0 / nowp;
? ? ? ? }
? ? ? ? printf("%.3lf\n" ,Ans);
? ? }
? ? return 0;
}
? ? ?有n個(gè)服務(wù)器,每個(gè)服務(wù)器都要安裝網(wǎng)線(必須也只能安裝一個(gè)),然后每個(gè)服務(wù)器都有mi種選擇網(wǎng)線的方式,每種方式兩個(gè)參數(shù),一個(gè)是速度b,另一個(gè)是價(jià)錢(qián)p,然后讓你找到一個(gè)最大的比值 minb/sump,就是所有的選擇中最小的那個(gè)速度,必上話的錢(qián)的總和。
思路:?
? ? ? 這個(gè)題目按照討論組里面的說(shuō)法估計(jì)做法很多,不管了,說(shuō)下我自己的做法吧,我的做法有點(diǎn)像操作系統(tǒng)里面那個(gè)多路歸并(如果沒(méi)記錯(cuò)是叫這個(gè),做題的時(shí)候突然想到這個(gè)方式,試了下,還真行),具體是這樣,枚舉最小的b,也就是最小的那個(gè)帶寬,對(duì)于每個(gè)服務(wù)器,我們可以先把他所有的可選擇項(xiàng)都按照帶寬從小到大排序,排序后再倒著預(yù)處理得到每個(gè)選項(xiàng)后面中最小的那個(gè)花費(fèi),全部這樣處理完之后就得到了一個(gè)二維的表,然后我們開(kāi)始枚舉,每個(gè)表都是根據(jù)帶寬從小到大排序的,這樣所有中最小的那個(gè)肯定就是某一個(gè)的第一項(xiàng),我們O(n)的時(shí)間找到第一項(xiàng),以這一項(xiàng)的帶寬為最小帶寬,花費(fèi)是當(dāng)前這個(gè)選項(xiàng)的花費(fèi),其他的就選最小的花費(fèi),然后刪除找到的這一項(xiàng),就這樣一直找到頭一個(gè)服務(wù)器的選項(xiàng)全都用完了位置,還有就是刪除項(xiàng)的時(shí)候可以開(kāi)一個(gè)一維數(shù)組,記錄當(dāng)前這個(gè)服務(wù)器已經(jīng)用到第幾項(xiàng)了,刪除第i個(gè)服務(wù)器的當(dāng)前項(xiàng),直接mk[i]++就行了,16msAC,總的時(shí)間復(fù)雜度最壞應(yīng)該是 O(n*n*n) 1000000吧。感覺(jué)思路有點(diǎn)瞎扯了,呵呵,題目不難,瞎扯就瞎扯吧,好就說(shuō)這些。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 100 + 10
#define INF 1000000000
using namespace std;
typedef struct
{
? ? int b ,p ,minp;
}NODE;
NODE node[N][N];
int now[N] ,num[N];
bool camp(NODE a ,NODE b)
{
? ? return a.b < b.b;
}
int main ()
{
? ? int t ,i ,j ,n ,tmp ,sn;
? ? scanf("%d" ,&t);
? ? while(t--)
? ? {
? ? ? ? scanf("%d" ,&n);
? ? ? ? for(i = 1 ,sn = 0 ;i <= n ;i ++)
? ? ? ? {
? ? ? ? ? ? scanf("%d" ,&num[i]);
? ? ? ? ? ? sn += num[i];
? ? ? ? ? ? for(j = 1 ;j <= num[i] ;j ++)
? ? ? ? ? ? scanf("%d %d" ,&node[i][j].b ,&node[i][j].p);
? ? ? ? ? ? sort(node[i] + 1 ,node[i] + num[i] + 1 ,camp);
? ? ? ? ? ? for(j = num[i] ;j >= 1 ;j --)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if(j == num[i] || tmp > node[i][j].p)
? ? ? ? ? ? ? ? tmp = node[i][j].p;
? ? ? ? ? ? ? ? node[i][j].minp = tmp;
? ? ? ? ? ? }
? ? ? ? ? ? now[i] = 1;
? ? ? ? }
? ? ? ? double Ans = 0;
? ? ? ? int nowb ,nowp;
? ? ? ? while(sn--)
? ? ? ? {
? ? ? ? ? ? nowb = INF;
? ? ? ? ? ? nowp = 0;
? ? ? ? ? ? int mkbreak = 0;
? ? ? ? ? ? for(i = 1 ;i <= n ;i ++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if(now[i] > num[i]) mkbreak = 1;
? ? ? ? ? ? ? ? if(nowb > node[i][now[i]].b)
? ? ? ? ? ? ? ? nowb = node[i][now[i]].b;
? ? ? ? ? ? }
? ? ? ? ? ? if(mkbreak) break;
? ? ? ? ? ? int mk = 0;
? ? ? ? ? ? for(i = 1 ;i <= n ;i ++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? //if(now[i] > num[i]) continue;
? ? ? ? ? ? ? ? if(!mk && nowb == node[i][now[i]].b)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? mk = 1;
? ? ? ? ? ? ? ? ? ? nowp += node[i][now[i]].p;
? ? ? ? ? ? ? ? ? ? now[i] ++;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? else nowp += node[i][now[i]].minp;
? ? ? ? ? ? }
? ? ? ? ? ? if(Ans < nowb * 1.0 / nowp)
? ? ? ? ? ? Ans = nowb * 1.0 / nowp;
? ? ? ? }
? ? ? ? printf("%.3lf\n" ,Ans);
? ? }
? ? return 0;
}
總結(jié)
以上是生活随笔為你收集整理的POJ1018贪心(多路归并的想法)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: POJ2771最大独立集元素个数
- 下一篇: POJ1548最小路径覆盖