列表

详情


NC15600. 小Y写文章

描述

小Y写了一篇文章,他对自己的文笔很有自信,尤其是自己总结出了一套计算文章通顺性的公式。

文章共N段,对于文章的每一段小Y对它都能计算出一个估值,而一篇文章的不连贯值定义为,现在小Y想要发布他的文章,但是编辑小Z让他加入一些广告,具体来说就是M段估值分别为的新段落。小Y很头疼,想让修改后的文章依然通顺,也就是要最小化不连贯值,已知小Y加入新段落的时候不需要考虑新段落之间的顺序,但是只可以在原文章的开头段之前、结尾段之后、或两段之间加入一段新段落,每个位置只能加入最多一段。请帮助焦头烂额的小Y求出将这M个新段落都加入之后的最小不连贯值。


输入描述

多组数据,第一行有一个正整数表示数据组数。

之后有T组数据,每组数据第一行有两个整数

接着有两行,其中第一行有N个正整数,表示原文章按顺序每段的估值。

第二行有M个正整数,表示新段落每段的估值。

输出描述

对于每组数据,输出一个整数表示求出的最小不连贯值。

示例1

输入:

2
4 3
1 6 5 2
3 1 4
4 2
1 2 4 3
10 10

输出:

3
7

说明:

第一组样例方案可以是 (1) 1 (4) 6 5 (3) 2
第二组样例方案可以是 1 2 4 (10) 3 (10)

原站题解

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

C++11(clang++ 3.9) 解法, 执行用时: 786ms, 内存消耗: 608K, 提交时间: 2018-04-15 15:54:33

#include<bits/stdc++.h>
using namespace std;
int t,n,m,i,j,l,r,mid,a[205],b[205],d[205][205],c[205];
bool v[205];
int A(int x)
{
	if(x<0)return -x;
	return x;
}
bool dfs(int x)
{
	for(int i=1;i<=n;i++)if(!v[i]&&d[x][i]<=mid)
	{
		v[i]=1;
		if(!c[i]||dfs(c[i]))
		{
			c[i]=x;
			return 1;
		}
	}
	return 0;
}
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		for(i=1;i<=n;i++)scanf("%d",a+i);
		for(i=1;i<=m;i++)
		{
			scanf("%d",b+i);
			d[i][1]=A(b[i]-a[1]);
			for(j=1;j<n;j++)d[i][j+1]=max(A(b[i]-a[j]),A(b[i]-a[j+1]));
			d[i][n+1]=A(b[i]-a[n]);
		}
		for(;i<=n+1;i++)
		{
			d[i][1]=0;
			for(j=1;j<n;j++)d[i][j+1]=A(a[j+1]-a[j]);
			d[i][n+1]=0;
		}
		n++;
		l=0;
		r=1000000000;
		while(l+1<r)
		{
			mid=l+r>>1;
			fill(c+1,c+n+1,0);
			for(i=1;i<=n;i++)
			{
				fill(v+1,v+n+1,0);
				if(!dfs(i))break;
			}
			if(i>n)r=mid;
			else l=mid;
		}
		cout<<r<<endl;
	}
	return 0;
}

上一题