B.好伙计猜拳

题目链接:https://ac.nowcoder.com/acm/contest/95338/B

题意:

给定a,b两个数组,有操作1:花费c1的代价删除ai,bi这一条记录 操作2:花费c2的代价交换ai,bi的值
求令a,b都成为最长不递减子序列的最低代价

思路:

类似与LIS,通过n方dp实现
开一个二维dp,初始化为inf,dp[0][0]=0,dp[0][1]=0.表示第0条记录作结尾时花费的代价
dp[i][0]代表以第i条记录为结尾,且第i条记录不交换。dp[i][1]代表以第i条记录为结尾,且第i条记录交换
观察 枚举j<i时, 当 aj<=ai,bj<=bi 或 aj<=bi,bj<=ai 或 bj<=ai,aj<=bi 时 发生条件转移(删除i~j之间的记录即可满足条件)
答案不一定是dp[n][0],dp[n][1]的最小值,因此取答案时要加上删除后缀的记录的代价 c1*(n-i)

#include<bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define pb push_back
#define int long long
#define endl "\n"
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int inf=0x3f3f3f3f;
const ll llmax=LLONG_MAX;
const int maxn=1e5+5;
int n,c1,c2;
int dp[1005][2];
int a[1005];
int b[1005];
signed main()
{
	ios::sync_with_stdio(false),cin.tie(0);
	int t;cin>>t;
	while(t--){
		int ans=llmax; 
		cin>>n>>c1>>c2;
		rep(i,1,n){
			cin>>a[i]>>b[i];	
		}
		memset(dp,inf,sizeof(dp));
		dp[0][0]=0;
        dp[0][1]=0;
		rep(i,1,n){
			for(int j=0;j<i;j++){
				if(a[i]>=a[j]&&b[i]>=b[j]){
					dp[i][0]=min(dp[i][0],dp[j][0]+(i-j-1)*c1);
				}
				if(a[i]>=b[j]&&b[i]>=a[j]){
					dp[i][0]=min(dp[i][0],dp[j][1]+(i-j-1)*c1);
				}
			}
			for(int j=0;j<i;j++){
				if(a[i]>=b[j]&&b[i]>=a[j]){
					dp[i][1]=min(dp[i][1],c2+dp[j][0]+(i-j-1)*c1);
				}
				if(a[i]>=a[j]&&b[i]>=b[j]){
					dp[i][1]=min(dp[i][1],c2+dp[j][1]+(i-j-1)*c1);
				}
			}
			ans=min(ans,min(dp[i][0],dp[i][1])+(n-i)*c1);
		}
		cout<<ans<<endl;
	}
	return 0;
}


posted @   Marinaco  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示