其他分享
首页 > 其他分享> > P2577 [ZJOI2005]午餐

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