专栏文章

P12986 [GCJ 2022 #1A] Weightlifting 题解

P12986题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minazlfh
此快照首次捕获于
2025/12/01 23:27
3 个月前
此快照最后确认于
2025/12/01 23:27
3 个月前
查看原文

思路分析:

数据范围是 100100,那么容易想到区间 DP。定义 Fl,rF_{l,r} 表示完成动作 lrl\sim r 所需最小操作次数。转移如下: Fl,r=mink=lr1Fl,k+Fk+1,r2×Gl,rF_{l,r}=\min_{k=l}^{r-1}F_{l,k}+F_{k+1,r}-2\times G_{l,r} 其中 Gi,jG_{i,j} 表示动作 lrl\sim r 中重复的配重数(不必要的操作,直接压栈底即可),让 rrl+1l+1 往右扫求出每个配重的最小值累加起来即可。为什么是 l+1l+1?就算是重复的 ll 处也得加进去,还有最后要拿走,所以不能到 ll。初始化为 Fi,i=2×Gi,iF_{i,i}=2\times G_{i,i},这里和上述转移的二倍皆为 11 次放入 11 次拿出。

AC Code:

CPP
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int x[N][N],f[N][N],g[N][N],mn[N];
void solve(){
	memset(g,0,sizeof(g));
	memset(f,0x3f,sizeof(f));
	int e,w;cin>>e>>w;
	for(int i=1;i<=e;i++){
		for(int j=1;j<=w;j++)
			cin>>x[i][j],g[i][i]+=x[i][j];
		f[i][i]=2*g[i][i];
	}
	for(int l=1;l<=e;l++){
		for(int j=1;j<=w;j++)mn[j]=x[l][j];
		for(int r=l+1;r<=e;r++){
			for(int j=1;j<=w;j++)mn[j]=min(mn[j],x[r][j]);
			for(int j=1;j<=w;j++)g[l][r]+=mn[j];
		}
	}
	for(int len=2;len<=e;len++)
		for(int l=1,r=len;r<=e;l++,r++)
			for(int k=l;k<r;k++)
				f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]-2*g[l][r]);
	cout<<f[1][e]<<'\n';
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
    int T;cin>>T;for(int i=1;i<=T;i++)
    cout<<"Case #"<<i<<": ",solve();
    return 0;
}
完结撒花!!!

评论

0 条评论,欢迎与作者交流。

正在加载评论...