排位赛2-Snakes

排位赛2-Snakes

题目

According to legend, St. Patrick banished all of the snakes in Mooland over a thousand years ago. However, snakes have since made their way back to Mooland! St. Patrick’s day was on March 17, so Bessie is going to commemorate St. Patrick by banishing all of the snakes from Mooland once and for all. Bessie is equipped with a net to capture snakes distributed in N groups on a line (1≤N≤400). Bessie must capture every snake in every group in the order that the groups appear on the line. Each time Bessie captures a group, she can put the snakes in a cage and start with an empty net for the next group.

A net with size s means that Bessie can capture any group that contains g snakes, where g≤s. However, every time Bessie captures a group of snakes of size g with a net of size s, she wastes s−g space. Bessie’s net can start at any size and she can change the size of her net K times (1≤K<N).

Please tell Bessie the minimum amount of total wasted space she can accumulate after capturing all the groups.

题意

有n团蛇,每团蛇都有一个数量,现在要重第一团蛇开始捕捉他们,一开始你可以设置你网的容量,后面又k次修改的机会,一次捕捉的亏损即捕捉这团蛇后网剩余的容量,求最小亏损。

解法

DP,f[i][j][k]表示第i团蛇网下容量为jx网的容量修改了k次的最小亏损,因为每团蛇的数量较大而蛇的团数较小,所以得将每团蛇得数量离散化,然后我们可以得到状态转移方程,f[i][j][k]=min(f[i-1][j][k],f[i -1][z][k-1])+j-a[i],明显可用滚动数组,如果每次都枚举z很明显时间上会超,其实只需要取k-1状态中最小值就可以了,这个可以在滚动数组交换时一起做了。

代码:

#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <math.h>
using namespace std;
const int maxn=410;
const int maxd=400000010;
int n,m,l,ans,a[1000010],c[1000010],d[1000010],f[maxn][maxn],ff[maxn][maxn],smin[maxn];
struct CC
{
	int id,x;
}b[maxn];


bool rmp(CC x,CC y) 
{
	return x.x<y.x;
}

int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) 
	{
		scanf("%d",&a[i]);
		b[i].x=a[i];
		b[i].id=i;
	}
	sort(b+1,b+n+1,rmp);
	l=0;
	b[0].x=-1;
	for (int i=1;i<=n;i++) 
	{
		if (b[i].x!=b[i-1].x) 
		{
			l++;
			c[b[i].x]=l;
			d[l]=b[i].x;
		} 
	}
	for (int i=1;i<=n;i++) a[i]=c[a[i]];
	for (int i=1;i<=m+1;i++) 
	for (int j=1;j<=l;j++) 
	{
		f[i][j]=maxd;
		ff[i][j]=maxd;
		smin[j]=maxd;
	}
	for (int i=a[1];i<=l;i++) ff[1][i]=min(ff[1][i],d[i]-d[a[1]]);
	smin[0]=maxd;
	for (int k=1;k<=l;k++) 
	{
		smin[1]=min(smin[1],ff[1][k]);
	}
	for (int i=2;i<=n;i++) 
	{
		for (int j=1;j<=m+1;j++)
		{
			for (int k=a[i];k<=l;k++) 
			{
				f[j][k]=min(f[j][k],ff[j][k]+d[k]-d[a[i]]);
				f[j][k]=min(f[j][k],smin[j-1]+d[k]-d[a[i]]);
			}
		}
		for (int j=1;j<=m+1;j++) 
		{
			smin[j]=maxd;
			for (int k=1;k<=l;k++) 
			{
				ff[j][k]=f[j][k];
				smin[j]=min(smin[j],f[j][k]);
				f[j][k]=maxd;
			}
		}
		smin[0]=maxd;
	}
	ans=maxd;
	for (int j=1;j<=m+1;j++)
	for (int i=1;i<=l;i++) ans=min(ans,ff[j][i]);
	printf("%d",ans);
	return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值