1. 程式人生 > >P2577 [ZJOI2005]午餐

P2577 [ZJOI2005]午餐

數組 max -- pos 現在 可能 can int 要求

題目描述

上午的訓練結束了,THU ACM小組集體去吃午餐,他們一行N人來到了著名的十食堂。這裏有兩個打飯的窗口,每個窗口同一時刻只能給一個人打飯。由於每個人的口味(以及胃口)不同,所以他們要吃的菜各有不同,打飯所要花費的時間是因人而異的。另外每個人吃飯的速度也不盡相同,所以吃飯花費的時間也是可能有所不同的。

THU ACM小組的吃飯計劃是這樣的:先把所有的人分成兩隊,並安排好每隊中各人的排列順序,然後一號隊伍到一號窗口去排隊打飯,二號隊伍到二號窗口去排隊打飯。每個人打完飯後立刻開始吃,所有人都吃完飯後立刻集合去六教地下室進行下午的訓練。

現在給定了每個人的打飯時間和吃飯時間,要求安排一種最佳的分隊和排隊方案使得所有人都吃完飯的時間盡量早。

假設THU ACM小組在時刻0到達十食堂,而且食堂裏面沒有其他吃飯的同學(只有打飯的師傅)。每個人必須而且只能被分在一個隊伍裏。兩個窗口是並行操作互不影響的,而且每個人打飯的時間是和窗口無關的,打完飯之後立刻就開始吃飯,中間沒有延遲。

現在給定N個人各自的打飯時間和吃飯時間,要求輸出最佳方案下所有人吃完飯的時刻。

輸入輸出格式

輸入格式:

第一行一個整數N,代表總共有N個人。

以下N行,每行兩個整數 Ai,Bi。依次代表第i個人的打飯時間和吃飯時間。

輸出格式:

一個整數T,代表所有人吃完飯的最早時刻。

輸入輸出樣例

輸入樣例#1: 復制
5
2 2
7 7
1 3
6 4
8 5
輸出樣例#1: 復制
17
//一維數組    
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inf 0x3fffffff
#define maxn 10000

//dp[j]:代表第一個隊伍排隊總時間為j時的最晚集合時間
//(註意是第一個隊伍!!!)
//第i個人選第一個隊伍時:
//加入第一隊進行的更新
//dp[j+p[i].a]=min(max(dp[j],j+p[i].b))
//加入第二隊進行的更新
//dp[j]=max(dp[j],sum[i]-j+p[i].b)


struct node
{
    
int a,b; } p[1000]; int n; int dp[400001]; int sum[1000]; int ans; bool cmp(node x,node y) { return x.b>y.b; } int main() { cin>>n; for(int i=1; i<=n; i++) cin>>p[i].a>>p[i].b; sort(p+1,p+1+n,cmp); fill(&dp[0],&dp[400000],inf); dp[0]=0; for(int i=1; i<=n; i++) sum[i]=p[i].a+sum[i-1]; for(int i=1; i<=n; i++) for(int j=sum[i]; j>=0; j--) { dp[j+p[i].a]=min(dp[j+p[i].a],max(dp[j],j+p[i].a+p[i].b)); dp[j]=max(dp[j],sum[i]-j+p[i].b); } ans=inf; for(int i=1; i<=sum[n]; i++) ans=min(ans,dp[i]); cout<<ans; return 0; }

//滾動數組
#include<cstdio>
#include<algorithm>
#include<cstring>
#define re register

using namespace std;

const int inf=0x3f3f3f3f;
const int N=205;

struct Goods
{
    int w,v;
    inline bool operator < (const Goods &rhs) const
    {
        return v>rhs.v;
    }
} a[N];
int n,sum[N],dp[2][N*N];
int main()
{
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
        scanf("%d%d",&a[i].w,&a[i].v);
    sort(a+1,a+n+1);
    for(int i=1; i<=n; i++)
        sum[i]=sum[i-1]+a[i].w;
    memset(dp,0x3f,sizeof(dp));
    dp[0][0]=0;
    for(int i=1; i<=n; i++)
    {
        re int cur=i&1,pre=cur^1;
//fill(&dp[cur][0],&dp[cur][N*N],inf);這麽清空好些
        memset(dp[cur],127,sizeof(dp[cur]));//只清空了當前cur這一層
        for(int j=sum[i]; j>=0; j--)
        {
            if (j>=a[i].w)
                dp[cur][j]=min(dp[cur][j],max(dp[pre][j-a[i].w],j+a[i].v));
            dp[cur][j]=min(dp[cur][j],max(dp[pre][j],sum[i]-j+a[i].v));
        }
    }
    re int ans=inf;
    for(int i=0; i<=sum[n]; i++)
        ans=min(ans,dp[n&1][i]);
    printf("%d",ans);
    return 0;
}

P2577 [ZJOI2005]午餐