P2577 [ZJOI2005]午餐
作者:互联网
贪心可得吃饭时间长的优先在前面打饭得到的解更优
证明过程:
假设第i个人打饭时间为a[i].da
,第i个人吃饭的时间为a[i].cf
,第j个人同理
假设a[i].cf>a[j].cf
**所以就有两种情况:
1.第i个人在第j个人的前面,此时设最后一个人吃完饭的时间为t1
t1=max(a[i].cf+a[i].da,a[j].da+a[j].cf+a[i].da);
2.若第j个人在第i个人前面,此时设最后一个人吃完饭的时间为t2
t2=max(a[j].cf+a[j].da,a[i].cf+a[i].da+a[j].da)
;**
t1中的第二项大于t2中的第一项,t2中的第2项大于t1中的第一项
又因为a[i].cf>a[j].cf 可以看出 t2中的第二项大于t1中的第二项所
以使第i个人在第j个人前面可以使结果更优(因为要使最大值最小),所以按照吃饭时间
的大小排序,大的在前,小的在后
关于dp方程式;设dp[i][j]
表示前i个人(排序后) 在第一个窗口排队的人排队的总时间为j的时候耗时最大的人所需要的时间
那么状态转移方程式为:
1.若第i个人选择在第一个窗口排队:
dp[i][j]=min(dp[i][j],max(dp[i-1][j-a[i].da]],j+a[i].cf));
2.若第i个人选择在第二个窗口排队:
dp[i][j]=min(dp[i][j],max(dp[i-1][j],sum[i]-j+a[i].cf));
sum[i]表示前i个人打饭消耗的时间的前缀和
#include<bits/stdc++.h>
using namespace std;
int n,sum[250];
int dp[250][50001];
struct node{
int df,cf;
}a[250];
bool cmp(node a,node b){
return a.cf>b.cf;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].df>>a[i].cf;
}
memset(dp,0x3f,sizeof(dp));
dp[0][0]=0;
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+a[i].df;
}
for(int i=1;i<=n;i++){
for(int j=0;j<=sum[i];j++){
if(j>=a[i].df) dp[i][j]=min(dp[i][j],max(dp[i-1][j-a[i].df],j+a[i].cf)); //如果第i个人在一号队排队并且前i个人在一号队排队的排队时间为j,的最小用时
dp[i][j]=min(dp[i][j],max(dp[i-1][j],sum[i]-j+a[i].cf));
}
}
int ans=12346678;
for(int i=1;i<=sum[n];i++){
ans=min(ans,dp[n][i]);
}
cout<<ans;
}
标签:个人,int,max,午餐,cf,da,P2577,ZJOI2005,dp 来源: https://blog.csdn.net/qq_42807300/article/details/97616840