LUOGU P2577 [ZJOI2005]午餐
解题思路
贪心+dp。首先一定是让吃的慢的先吃这是很显然的,所以按照b[i]排一遍序,然后考虑dp,设dp[i][j]表示前i个人第一个队伍的排队时间为j的最小时间,转移比较容易理解
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; const int MAXN = 205; inline int rd(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return f?x:-x; } int n,sum[MAXN],ans=1e9; int dp[MAXN][MAXN*MAXN]; struct Data{ int a,b; }data[MAXN]; inline bool cmp(Data A,Data B){ return A.b>B.b; } int main(){ memset(dp,0x3f,sizeof(dp)); n=rd();dp[0][0]=0; for(int i=1;i<=n;i++) data[i].a=rd(),data[i].b=rd(); sort(data+1,data+1+n,cmp); for(int i=1;i<=n;i++) sum[i]=sum[i-1]+data[i].a; for(int i=1;i<=n;i++) for(register int j=0;j<=sum[i];j++){ if(j>=data[i].a) dp[i][j]=max(dp[i-1][j-data[i].a],j+data[i].b); dp[i][j]=min(dp[i][j],max(dp[i-1][j],sum[i]-j+data[i].b)); } for(int i=0;i<=sum[n];i++) ans=min(ans,dp[n][i]); cout<<ans<<endl; return 0; }