【POJ】1821 Fence栅栏

【POJ】1821 Fence栅栏

Time Limit: 1000MS
Memory Limit: 30000K

Description

A team of k (1 <= K <= 100) workers should paint a fence which contains N (1 <= N <= 16 000) planks numbered from 1 to N from left to right. Each worker i (1 <= i <= K) 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 Pi $ (1 <= Pi <= 10 000). 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.
Input

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

Output

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

Sample Input

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

Sample Output

17

Hint

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

翻译

栅栏

时限: 1000MS
内存限制: 30000K

描述

由k(1 <= K <= 100)个工人组成的团队应油漆围墙,其中包含N(1 <= N <= 16 000)个从左到右从1到N编号的木板。每个工人i(1 <= i <= K)应该坐在木板Si的前面,并且他只能喷涂一个紧凑的间隔(这意味着该间隔中的木板应该是连续的)。此间隔应包含Si板。同样,工人涂的油漆不能超过李木板,每涂一块木板,他应得到Pi $(1 <= Pi <= 10000)。一块木板最多只能由一个工人涂油漆。所有数字Si应该是不同的。

作为团队的负责人,您要确定每个工人的油漆间隔,但要知道总收入应该是最大的。总收入是工人个人收入的总和。

编写一个程序,确定K工人获得的最大总收入。

输入

输入包含:

输入

N K
L1 P1 S1
L2 P2 S2

LK PK SK

简化

N-木板数;?工人数
Li-工人i可以涂漆的木板的最大数量-Pi-工人i
收到的已涂漆的木板
Si的总和-工人 坐在前面的木板i

输出

输出包含单个整数,即最大总收入。

样本输入

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

样本输出

17

暗示

样本说明:

工人1喷涂间隔[1、2];在步骤1喷涂间隔1。

工作人员2绘制间隔[3,4];

工人3喷涂间隔[5、7];

工人4不涂任何木板

思路

DP
f [ i ] [ j ] = m a x ( f [ i ] [ j − 1 ] , f [ i − 1 ] [ j ] , m a x ( f [ i − 1 ] [ k ] + p [ i ] ∗ ( j − k ) ( m a x ( 0 , s [ i ] − l [ i ] ) < = k < = m i n ( j , s [ i ] − 1 ) ) f[i][j]=max(f[i][j−1],f[i−1][j],max(f[i−1][k]+p[i]∗(j−k)(max(0,s[i]−l[i])<=k<=min(j,s[i]−1)) f[i][j]=max(f[i][j1],f[i1][j],max(f[i1][k]+p[i](jk)(max(0,s[i]l[i])<=k<=min(j,s[i]1))
用单调性处理max(f[i−1][k]+p[i]∗(j−k)。

代码

#include<iostream>
#include<cstdio>
#include<deque>
#include<algorithm>
using namespace std;
struct jgt
{
    
    
	int s,l,p;
}a[110];
deque<int> que;
int f[110][16010];
bool cmp(jgt t1,jgt t2)
{
    
    
	return t1.s<t2.s;
}
int main()
{
    
    
	int n,k,i,j;
	scanf("%d%d",&n,&k);
	for(i=1;i<=k;i++)
		scanf("%d%d%d",&a[i].l,&a[i].p,&a[i].s);
	sort(a+1,a+k+1,cmp);
	for(i=1;i<=k;i++)
	{
    
    
		que.clear();
		que.push_back(max(0,a[i].s-a[i].l)); 
		for(j=1;j<=n;j++)
		{
    
    
			f[i][j]=max(f[i-1][j],f[i][j-1]);
			if(j<a[i].s+a[i].l)
			{
    
    
				for(;!que.empty()&&que.front()+a[i].l<j;que.pop_front());//找不在范围内数
				if(j<a[i].s)
				{
    
    
					for(;!que.empty()&&f[i-1][que.back()]+a[i].p*(j-que.back())<f[i-1][j];que.pop_back());//删除过小的数
					que.push_back(j);
				}
				else
					f[i][j]=max(f[i][j],f[i-1][que.front()]+a[i].p*(j-que.front()));
			}
		}
	}
	printf("%d",f[k][n]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_46975572/article/details/114415117