列表

详情


NC51195. Fence

描述

A team of k workers should paint a fence which contains N planks numbered from 1 to N from left to right. Each worker i should sit in front of the plank Si and he may paint only a compact interval (this means that the planks from the interval should be consecutive). This interval should contain the Si plank. Also a worker should not paint more than Li planks and for each painted plank he should receive . A plank should be painted by no more than one worker. All the numbers Si should be distinct.
Being the team's leader you want to determine for each worker the interval that he should paint, knowing that the total income should be maximal. The total income represents the sum of the workers personal income.
Write a program that determines the total maximal income obtained by the K workers.

输入描述

The input contains: 
Input 
N K 
L1 P1 S1 
L2 P2 S2 
... 
LK PK SK 
Semnification 
N -the number of the planks; K ? the number of the workers 
Li -the maximal number of planks that can be painted by worker i 
Pi -the sum received by worker i for a painted plank 
Si -the plank in front of which sits the worker i 

输出描述

The output contains a single integer, the total maximal income.

示例1

输入:

8 4
3 2 2
3 2 3
3 3 5
1 1 7 

输出:

17

说明:

Explanation of the sample:
the worker 1 paints the interval [1, 2];
the worker 2 paints the interval [3, 4];
the worker 3 paints the interval [5, 7];
the worker 4 does not paint any plank

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 13ms, 内存消耗: 6736K, 提交时间: 2020-04-10 11:06:45

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
struct node
{
	int L,P,S;
}a[110];
int n,m,dp[110][16010],q[16010];
bool operator<(node A,node B)
{
	return A.S<B.S;
}
int cal(int i,int k)
{
	return dp[i-1][k]-a[i].P*k;
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
		scanf("%d %d %d",&a[i].L,&a[i].P,&a[i].S);
	sort(a+1,a+1+m);
	for(int i=1;i<=m;i++)
	{
		int head=1,tail=0;//初始化单调队列
		for(int k=max(0,a[i].S-a[i].L);k<=a[i].S-1;k++)//最初的候选集合插入队列 
		{
			while(head<=tail&&cal(i,q[tail])<=cal(i,k))
				tail--;
			q[++tail]=k;
		}
		for(int j=1;j<=n;j++)
		{
			dp[i][j]=max(dp[i-1][j],dp[i][j-1]);//不粉刷时的转移
			if(j>=a[i].S)//粉刷第k+1~j块木板时的转移 
			{
				while(head<=tail&&q[head]<j-a[i].L)//排除队头不合法转移 
					head++;
				if(head<=tail)
					dp[i][j]=max(dp[i][j],cal(i,q[head])+a[i].P*j);
			} 
		} 
	}
	cout<<dp[m][n]<<endl;
	return 0;
} 

C++(g++ 7.5.0) 解法, 执行用时: 10ms, 内存消耗: 6660K, 提交时间: 2023-02-02 12:05:31

#include<iostream>
#include<algorithm>
using namespace std;

struct worker
{
    int l,p,s;
}a[105];

int n,m,f[105][16005],q[16005];

bool operator<(worker a,worker b) { return a.s<b.s;}

inline int calc(int i,int k) { return f[i-1][k]-a[i].p*k; }

int main(void)
{
    cin>>n>>m;
    for(int i=1;i<=m;i++) cin>>a[i].l>>a[i].p>>a[i].s;
    sort(a+1,a+m+1);
    for(int i=1;i<=m;i++)
    {
        int l=1,r=0;
        for(int k=max(a[i].s-a[i].l,0);k<=a[i].s-1;k++)
        {
            while(l<=r&&calc(i,k)>=calc(i,q[r])) r--;
            q[++r]=k;
        }
        for(int j=1;j<=n;j++)
        {
            f[i][j]=max(f[i-1][j],f[i][j-1]);
            if(j<a[i].s) continue;
            while(l<=r&&q[l]<j-a[i].l) l++;
            if(l<=r) f[i][j]=max(f[i][j],calc(i,q[l])+a[i].p*j);
        }
    }
    cout<<f[m][n]<<endl;
    return 0;
}

C++ 解法, 执行用时: 12ms, 内存消耗: 7040K, 提交时间: 2021-10-09 00:47:45

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int f[110][20000],n,m;
struct node
{
    int l,p,s;
}a[200010];
bool cmp(node a,node b)
{
    return a.s<b.s;
}
int main()
{
    cin>>m>>n;
    for(int i=1;i<=n;i++)cin>>a[i].l>>a[i].p>>a[i].s;
    sort(a+1,a+1+n,cmp);
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    {
        f[i][j]=max(f[i-1][j],f[i][j-1]);
        if(j>=a[i].s&&j-a[i].s+1<=a[i].l)
        {
            for(int l=max(1,j-a[i].l+1);l<=a[i].s;l++)
            f[i][j]=max(f[i][j],f[i-1][l-1]+(j-l+1)*a[i].p);
        }
    }
    cout<<f[n][m]<<endl;
}

上一题