POJ 2675 Songs

题意:一张CD上有n首频率为f[i],长度为了l[i]的曲子,因为CD不能随机播放曲子,想播放第i首时,必须依次播放前i-1,

b[i]=f[i]*(a[1]+...+a[i]),sum=b[1]+..+b[n],求使sum最小的歌曲排列方式。

分析:因为1<=n<=2^16,时效只可能是O(nlogn)或O(n),

一开始以为是按频率排序,发现测试数据都过不了。

若已得到最优排列,使最优值为m

b[i+1]+b[i]=f[i+1]*l[i]+(f[i+1]+f[i])*(l[1]+...+l[i-1])+f[i+1]*l[i+1]+f[i]*l[i];

若交换

f[i]*l[i+1]+(f[i+1]+f[i])*(l[1]+...+l[i-1])+f[i+1]*l[i+1]+f[i]*l[i];

两个相减,res=f[i+1]*l[i]-f[i]*l[i+1];

i若res<0,通过交换取得m+res;

#include<cstdio>
#include<algorithm>
#define MAXN 100010
using namespace std;

struct Song
{
    int i;
    double l,f;
};

Song s[MAXN];

bool Cmp(Song a, Song b)
{
    return b.f*a.l-a.f*b.l<0;
}

int main()
{
    int n,m,i,j,k;
    for(;scanf("%d",&n)+1;)
    {
        for(i=0;i<n;i++)
            scanf("%d%lf%lf",&s[i].i,&s[i].l,&s[i].f);
        scanf("%d",&m);
        sort(s,s+n,Cmp);
        printf("%d\n",s[m-1].i);
    }
    return 0;
原文地址:https://www.cnblogs.com/xchaos/p/2530976.html