题解 CF1239E Turtle

题意

一只乌龟从 2×n 的棋盘的左上角走到右下角,只能往下或往右,需要给出一种方案来分配 2×n 个数字使得乌龟走过的路径上的数之和的最大值最小。

2n250a1,i,a2,i50000

找性质

首先乌龟的路线一定是从 (1,1) 走到 (1,x),接着往下走到 (2,x),然后向右走到 (2,n)。其中 x 满足 1xn

性质 1第一行的数单调不降,第二行的数单调不升

证明:假设第一行存在 i,j 满足 i<ja1,i>a1,j,那么交换这两个位置。容易发现当 x[i,j) 这段区间时,答案变小了。否则不变。因此一定更优。第二行同理。

性质 2第一小的和第二小的数在 (1,1)(2,n)

证明:根据性质 1,第一排 (1,1) 最小,第二排 (2,n) 最小。因此最小的一定在 (1,1)(2,n)。由于中心对称,不妨在 (1,1)。第二小只能在 (1,2)(2,n)。容易发现 x=1 时在 (2,n) 更优,x>1 时两者等价。因此第二小的数在 (2,n)

性质 3x=1x=n,即乌龟只会在 (1,1)(1,n) 往下走最优

证明:假设 1<x<n,可知在 x 往下走的得分大于 x1x+1。因此:a1,x>a2,x1a1,x+1<a2,x。推导一下:a1,x>a2,x1a2,x>a1,x+1,所以 a1,x>a1,x+1,不符合性质 1。因此 x=1x=n

然后…

首先填入 (1,1)(2,n)。剩下的 2×n2 个数分成两组 n1 个数,要求最大值最小,也就是差最小。于是暴力跑背包加上 bitset 优化。复杂度 O(n2×aw)

代码

如果不输出方案的话,大概长这样…

int main()
{
	n=read();
	for (int i=1;i<=2*n;i++) a[i]=read();
	sort(a+1,a+n*2+1);
	dp[0][0]=1;
	for (int i=3;i<=2*n;i++)
	{
		int u=min(i-2,n-1);
		s+=a[i];
		for (int j=u;j>=1;j--)
		{
			dp[j]|=(dp[j-1]<<a[i]);
		}
	}
	int ans=1e9;
	for (int i=0;i<=s;i++)
	{
		if (dp[n-1][i]) ans=min(ans,max(i,s-i));
	}
	cout << a[1]+a[2]+ans << endl;
	return 0;
}

然后惊奇地发现输出方案不是很好弄。于是我们把背包的滚动数组还原,增加原来的第一维。这样就可以输出方案了!

//注意:read、输出方案部分已省略
#include <bits/stdc++.h>
using namespace std;
const int N=26,M=50005;
int n; 
int a[N*2],s,p[N];
bitset<M*N*2>dp[2*N][N];
bool used[2*N];
int main()
{
	n=read();
	for (int i=1;i<=2*n;i++) a[i]=read()+1;
	sort(a+1,a+n*2+1);
	dp[2][0][0]=1;
	for (int i=3;i<=2*n;i++)
	{
		int u=min(i-2,n-1);
		s+=a[i];
		for (int j=u;j>=1;j--)
		{
			dp[i][j]=dp[i-1][j]|(dp[i-1][j-1]<<a[i]);
		}
		dp[i][0]=dp[i-1][0];
	}
	int ans=1e9;
	for (int i=0;i<=s;i++)
	{
		if (dp[2*n][n-1][i]) ans=min(ans,max(i,s-i));
	}
	int tot=2*n,u=n-1;
	while (ans)
	{
		if (dp[tot-1][u][ans]) tot--;
		else used[tot]=1,ans-=a[tot],tot--,u--;
	}
	//used=0的是一组,used=1的是另一组
	//不要忘了a[1]和a[2]
	return 0;
}

这个做法比不用 bitset 的 O(n2×a) 快多了。

posted @   Little09  阅读(60)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示