zoukankan      html  css  js  c++  java
  • 洛谷P2577 [zjoi2004]午餐---贪心+dp

    题目链接:https://www.luogu.com.cn/problem/P2577

    简单题意:两个窗口打饭,每个人有打饭和吃饭时间,求最快全部吃完的时间

    让吃饭时间长的先打饭,应该比较容易想到,不管窗口数量是多少。但是之后就开始胡乱设计状态了。一开始想了个sb状态:dp[i][1/2]表示轮到第i个人,选择窗口1/2的最小时间,发现根本写不出来方程......

    正解是设 f[i][j]表示前i个人在窗口1打饭时间为j,吃完饭的最早时间。有点难想到,而且这个状态怎么只考虑了一个窗口?其实原方程是 f[i][j][k]表示前i个人,在1窗口打饭时间为j,2窗口为k的最早时间,由于j+k是定值,所以可以去掉一维。转移方程看代码吧,其实有点像个背包问题(细节:有可能第i个人吃完饭了,之前的人还没吃完)。另外这个初始化纠结了一会,一开始总是想前i个人如果打饭时间不能为j怎么办,其实全初始化为inf就行了

    #include<bits/stdc++.h>
    #define ll long long 
    using namespace std;
    
    struct st{int c,d;}a[210];
    int n,i,j,k,ans,f[210][210*210],sum[210];
    bool cmp(st p,st q){return p.c>q.c;}
    //f[i][j]: 前i个人在窗口1打饭时间为j的最小结束时间 
    
    int main(){
    	cin>>n;
    	for (i=1;i<=n;i++) cin>>a[i].d>>a[i].c;
    	sort(a+1,a+n+1,cmp); //吃饭时间降序 
    	for (i=1;i<=n;i++) sum[i]=sum[i-1]+a[i].d;
    	memset(f,0x3f,sizeof(f)); f[0][0]=0; //*
    	for (i=1;i<=n;i++)
    	  for (j=0;j<=sum[i];j++){
    	  	if (j-a[i].d>=0) f[i][j]=max(j+a[i].c,f[i-1][j-a[i].d]); //i放在队1 
    	  	f[i][j]=min(f[i][j],max(sum[i]-j+a[i].c,f[i-1][j]));  //i放在队2 
    	  }
    	ans=1e9;
    	for (i=0;i<=sum[n];i++) ans=min(ans,f[n][i]);
    	cout<<ans<<endl;
    	return 0;
    }
    

      

  • 相关阅读:
    python学习day02
    鼓起勇气 大胆说不
    spring系列---- spring-mvc1
    win7-64位 jdk安装
    项目分层以及阶段期限规划
    老油条之记
    论软件与管理的关系---企业管理软件的末路
    软件项目管理之觞
    世界在变化-----谷歌不安全
    LPR利率与固定利率哪个更合算?
  • 原文地址:https://www.cnblogs.com/edmunds/p/13423744.html
Copyright © 2011-2022 走看看