P1800 software 二分优化 DP

UserJCY / 2024-10-22 / 原文

P1800 software

很明显的二分,用 DP 写 check()

对于 check(t),转移方程:

\(dp_{i,j}\) 表示前 \(i\) 个人在做 \(j\) 个项目 1 的情况下最多能做的项目二的个数。

\[dp_{i,j} = \max_{k=1}^j dp_{i-1,k} + (t - a_i \times (j-k)) \div b_i \]

答案为:

\[dp_{n,m} \ge m \]

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m;
int a[110],b[110];
int dp[110][110];
bool check(int t){
	memset(dp,0,sizeof(dp));
	dp[0][0]=1;
	for(int i=1;i<=n;i++){
		for(int j=0;j<=m;j++){
			for(int k=0;k<=j;k++){
				int lft=t-(j-k)*a[i];
				if(lft>=0&&dp[i-1][k]>0)dp[i][j]=max(dp[i][j],dp[i-1][k]+lft/b[i]);
			}
		}
	} 
	return dp[n][m]>m;
}
signed main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i]>>b[i];
	}
	int l=1,r=1e9,mid;
	while(l<r){
		mid=(l+r)>>1;
		if(check(mid)){
			r=mid;
		}
		else{
			l=mid+1;
		}
	}
	cout<<r<<endl;
}