一本通1606【 例 1】任务安排 1

1606:【 例 1】任务安排 1

时间限制: 1000 ms         内存限制: 524288 KB

【题目描述】

有 N 个任务排成一个序列在一台机器上等待执行,它们的顺序不得改变。机器会把这 N 个任务分成若干批,每一批包含连续的若干个任务。从时刻 0 开始,任务被分批加工,执行第i个任务所需的时间是 Ti。另外,在每批任务开始前,机器需要 S 的启动时间,故执行一批任务所需的时间是启动时间 S 加上每个任务所需时间之和。

一个任务执行后,将在机器中稍作等待,直至该批任务全部执行完毕。也就是说,同一批任务将在同一时刻完成。每个任务的费用是它的完成时刻乘以一个费用系数 Ci 。

请为机器规划一个分组方案,使得总费用最小。

【输入】

第一行是 N。第二行是 S

下面 N 行每行有一对正整数,分别为 Ti和 Ci ,表示第 i 个任务单独完成所需的时间是 Ti 及其费用系数 Ci 。

【输出】

一个数,最小的总费用。

【输入样例】

5
1
1 3
3 2
4 3
2 3
1 4

【输出样例】

153

【提示】

样例说明:

分组方案为{1,2},{3},{4,5},则完成时间为 {5,5,10,14,14},费用 C={15,10,30,42,56},总费用为 153。

数据范围与提示:

对于全部数据,1N5000,0S50,1Ti,Ci100

sol:n3 应该很简单,dp[i][j]表示到第i个任务,分了几段(因为时间是有后效性的,处理起来很蛋疼

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read()
{
    ll s=0;
    bool f=0;
    char ch=' ';
    while(!isdigit(ch))
    {
        f|=(ch=='-'); ch=getchar();
    }
    while(isdigit(ch))
    {
        s=(s<<3)+(s<<1)+(ch^48); ch=getchar();
    }
    return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
    if(x<0)
    {
        putchar('-'); x=-x;
    }
    if(x<10)
    {
        putchar(x+'0');    return;
    }
    write(x/10);
    putchar((x%10)+'0');
    return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const int N=5005;
const ll inf=0x7fffffffff;
int n,S;
int Time[N],Cost[N],Time_Qzh[N],Cost_Qzh[N];
ll dp[N][N];
int main()
{
    int i,j,k;
    R(n); R(S);
    for(i=1;i<=n;i++)
    {
        Time_Qzh[i]=Time_Qzh[i-1]+(Time[i]=read());
        Cost_Qzh[i]=Cost_Qzh[i-1]+(Cost[i]=read());
    }
    memset(dp,63,sizeof dp);
    dp[0][0]=0;
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=i;j++)
        {
            for(k=j-1;k<=i-1;k++)
            {
                dp[i][j]=min(dp[i][j],dp[k][j-1]+1ll*(Time_Qzh[i]+S*j)*(Cost_Qzh[i]-Cost_Qzh[k]));
            }
        }
    }
    ll ans=inf;
    for(i=1;i<=n;i++) ans=min(ans,dp[n][i]);
    Wl(ans);
    return 0;
}
/*
input
5
1
1 3
3 2
4 3
2 3
1 4
output
153
*/
n^3做法

绞尽脑汁想n2dp做法,肯定是dp[i]表示前i个任务的最小权值,但这样是不行的

后来是这样的(并不知道dp[i]表示什么)

如果j~i是一段的

1):j~n之间要多S的时间 S*(Cost[n]-Cost[j-1]) ----> dp[i]

2):i到j之间的任务结束时间是 Time[i]  Time[i]*(Cost[i]-Cost[j-1]) ---->dp[i]

#include <bits/stdc++.h>
using namespace std;
typedef int ll;
inline ll read()
{
    ll s=0;
    bool f=0;
    char ch=' ';
    while(!isdigit(ch))
    {
        f|=(ch=='-'); ch=getchar();
    }
    while(isdigit(ch))
    {
        s=(s<<3)+(s<<1)+(ch^48); ch=getchar();
    }
    return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
    if(x<0)
    {
        putchar('-'); x=-x;
    }
    if(x<10)
    {
        putchar(x+'0');    return;
    }
    write(x/10);
    putchar((x%10)+'0');
    return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const int N=5005;
int n,S,dp[N];
ll Time[N],Cost[N];
int main()
{
    int i,j;
    R(n); R(S);
    for(i=1;i<=n;i++)
    {
        Time[i]=Time[i-1]+read(); Cost[i]=Cost[i-1]+read();
    }
    memset(dp,63,sizeof dp); dp[0]=0;
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=i;j++)
        {
            dp[i]=min(dp[i],dp[j-1]+Time[i]*(Cost[i]-Cost[j-1])+S*(Cost[n]-Cost[j-1]));
        }
    }
    Wl(dp[n]);
    return 0;
}
/*
input
5
1
1 3
3 2
4 3
2 3
1 4
output
153
*/
n^2做法

猜你喜欢

转载自www.cnblogs.com/gaojunonly1/p/10398523.html