题解 CF1239E Turtle
题意
一只乌龟从 的棋盘的左上角走到右下角,只能往下或往右,需要给出一种方案来分配 个数字使得乌龟走过的路径上的数之和的最大值最小。
,。
找性质
首先乌龟的路线一定是从 走到 ,接着往下走到 ,然后向右走到 。其中 满足 。
性质 :第一行的数单调不降,第二行的数单调不升。
证明:假设第一行存在 满足 ,,那么交换这两个位置。容易发现当 在 这段区间时,答案变小了。否则不变。因此一定更优。第二行同理。
性质 :第一小的和第二小的数在 和 。
证明:根据性质 ,第一排 最小,第二排 最小。因此最小的一定在 或 。由于中心对称,不妨在 。第二小只能在 或 。容易发现 时在 更优, 时两者等价。因此第二小的数在 。
性质 : 或 ,即乌龟只会在 或 往下走最优。
证明:假设 ,可知在 往下走的得分大于 和 。因此:,。推导一下:,所以 ,不符合性质 。因此 或 。
然后…
首先填入 和 。剩下的 个数分成两组 个数,要求最大值最小,也就是差最小。于是暴力跑背包加上 bitset 优化。复杂度 。
代码
如果不输出方案的话,大概长这样…
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 的 快多了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .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语句:使用策略模式优化代码结构