【线性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;
}
相关推荐
俊俊几年的26 分钟前
动态规划(Dynamic Programming)详解:从入门到 LeetCode Hot 100
linux·c++·算法·leetcode·嵌入式·动态规划·c
老歌老听老掉牙19 小时前
案例 7:二维 Rosenbrock 函数最小值(香蕉函数)
c++·pso
Severus_black19 小时前
【C++初阶】Stack、Queue算法题大练兵!
c语言·c++·算法·stl
xiaoye-duck1 天前
《C++ 项目:手写大模型接入 SDK》DataManager数据管理模块:SQLite持久化存储
开发语言·数据库·c++·sqlite
是main不是漫1 天前
【C++——类和对象(上)】筑基篇:以封装奠定面向对象之基
c语言·开发语言·c++
小七在进步1 天前
string的使用(1)
c++·visual studio
白杨尚青2 天前
C++进阶篇(六):map 和 set 的模拟实现——用红黑树封装 mymap/myset(迭代器 + operator[])
开发语言·c++·迭代器·stl·set·map·红黑树
kloc2 天前
聊天室项目入口网关子服务的实现
linux·c++
csdn_aspnet2 天前
C++ 3个有序点的方向(Orientation of 3 ordered points)
c++·算法
小七在进步2 天前
string的使用(2)
c++