【线性DP】P10156 [LSOT-2] 胜者组

解题思路

开一个结构体存储学生的序号、a值和c值。对输入的数据,先按c值排序,c值相同情况下按序号排序。

定义dp数组,dpij表示排序后的前i个人里,选了j人的最小满意度。

初始化:

bash 复制代码
memset(dp,0x3f,sizeof(dp));
for (int i = 0; i <= n; i++) dp[i][0] = 0;
  • 如果j是奇数,一种情况是如果前一个人和他同一个团体,不选第i个人,可以使dpij=dpi-1j;还有一种考虑选第i个人,dpij=min(dpij,dpi-1j-1+si.a-xsi.idx)。(+si.a-xsi.idx,我们可以这样考虑:最终t出去的人是偶数,现在j是奇数,所以根据不满意的计算ai+aj+x*|i-j|,后面会有一个数和j配对,这里就把j对应的序号si.idx减去)。
  • 如果j是偶数,一种情况是选第i个,且上一个人和第i个人同组,就可以得出dpij=min(dpij,dpi-1j-1+si.a+x*si.idx)。还有一种情况是不选第i个人,则dpij=min(dpij,dpi-1j)。

AC Code

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,m,k,x,dp[5005][5005];
struct stu{
	int a,c,idx;
	friend bool operator<(stu p,stu q){
		if(p.c!=q.c) return p.c<q.c;
		return p.idx<q.idx;
	}
}s[5005];
int main(){
	cin>>n>>m>>k>>x;
	m=n-m;
	if(m%2) m++;
	for(int i=1;i<=n;i++){
		s[i].idx=i;
		cin>>s[i].a;
	}
	memset(dp,0x3f,sizeof(dp));
	for (int i = 0; i <= n; i++) dp[i][0] = 0;
	for(int i=1;i<=n;i++)
		cin>>s[i].c;
	sort(s+1,s+n+1);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=min(i*1ll,m);j++){
			if(j%2!=0){
				if(s[i].c==s[i-1].c) dp[i][j]=dp[i-1][j];
				dp[i][j]=min(dp[i][j],dp[i-1][j-1]+s[i].a-x*s[i].idx);
			}
			else{
				dp[i][j]=dp[i-1][j];
				if(s[i].c==s[i-1].c) dp[i][j]=min(dp[i][j],dp[i-1][j-1]+s[i].a+x*s[i].idx);
			}
		}
	}
	if(dp[n][m]<1e18) cout<<dp[n][m];
	else cout<<"Impossible";
	return 0;
}
相关推荐
布莱克60513 分钟前
C++ 内存泄漏全解析:常见场景、成因与规避实践
开发语言·c++·内存泄露
jimy121 分钟前
lvalue、xvalue、prvalue(一):三者的分类
开发语言·c++
HAPPY酷1 小时前
C++ 内存泄漏排查:从裸 new 到 RAII 修复,附 ASan 实战
开发语言·c++
凯瑟琳.奥古斯特2 小时前
力扣1015C++解法技巧
c++·算法·leetcode·链表·职场和发展
悠仁さん2 小时前
【算法C++】双指针(一)
数据结构·c++·算法
jimy13 小时前
lvalue、xvalue、prvalue(二):引用是哪一类?
开发语言·c++·1024程序员节
杜 硕3 小时前
从零开始的C++生活——第三讲
开发语言·c++·生活
小成202303202653 小时前
C++~05异常处理
开发语言·c++
stolentime4 小时前
SOS DP学习笔记
c++·笔记·学习·算法·贪心算法·动态规划·二进制
用户7624117567054 小时前
第四章 流程控制结构
c++