https://jungol.co.kr/problem/5092?cursor=MTMsMCw0
만약 풀 문제를 정했다면, 어떤 순서대로 푸는것이 이득일까요? 이는 Exchange Argument로 최적화해줄 수 있습니다.
i번째 문제를 풀기 시작한 시각을 t라하면, i번째 문제를 푼 시각과 i+1번째 문제를 풀기 시작한 시각은 t+Ri이라고할 수 있고, i+1번째 문제를 푼 시각은 t+Ri+Ri+1이라고 할 수 있습니다. 이때의 점수는 (Mi-(t+Ri)Pi)+(Mi+1-(t+Ri+Ri+1)Pi+1)이라고 할 수 있습니다. 이때 두 문제의 푸는 순서를 바꾸면 점수가 (Mi+1-(t+Ri+1)Pi+1)+(Mi-(t+Ri+Ri+1)Pi)가 되며, 앞에 식이 더 크거나 같아야하므로 정리하면 R/P가 증가하는 순서대로 문제를 해결해주면 됩니다.
그러면 모든 문제를 정렬할 수 있게 됩니다. 여기서 dp[i][j]를 i번 문제까지 푸는데에 j의 시간이 걸렸을 때의 점수의 최댓값이라고 정의합시다. 이 dp테이블을 채워주면 문제를 해결할 수 있습니다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <array>
#define ll long long
using namespace std;
ll dp[55][101010]={0};
bool cmp(array <ll,3> A,array <ll,3> B) //{M,P,R}
{
return A[1]*B[2]>A[2]*B[1];
}
ll M[101010]={0},P[101010]={0},R[101010]={0};
int main()
{
ios_base::sync_with_stdio(false); cin.tie(NULL);
ll N,T,i,j;
cin>>N>>T;
for (i=1;i<=N;i++) cin>>M[i];
for (i=1;i<=N;i++) cin>>P[i];
for (i=1;i<=N;i++) cin>>R[i];
vector <array <ll,3> > v;
v.push_back({0,0,0});
for (i=1;i<=N;i++)
v.push_back({M[i],P[i],R[i]});
sort (v.begin()+1,v.end(),cmp);
for (i=1;i<=N;i++)
{
for (j=1;j<=T;j++)
{
dp[i][j]=dp[i-1][j];
if (j>=v[i][2])
dp[i][j]=max(dp[i][j],dp[i-1][j-v[i][2]]+v[i][0]-j*v[i][1]);
}
}
ll res=0;
for (i=1;i<=T;i++)
res=max(res,dp[N][i]);
cout<<res;
}

| 능력주의 회사 (JUNGOL 3998) (0) | 2026.04.22 |
|---|---|
| 미어캣 (JUNGOL 5602) (0) | 2026.04.21 |
| 쿠폰 (JUNGOL 3762) (0) | 2026.04.20 |
| 구두 수선공 (JUNGOL 6271) (0) | 2026.04.20 |
| Simply Sitting on Chairs (CF R 1089 Div.2 - B) (0) | 2026.04.19 |