• 洛谷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;
    }
    

      

  • 相关阅读:
    WPF 自定义CheckBox样式
    WPF中的动画——(二)From/To/By 动画
    C# 异步编程
    C# 二维码生成 ( QRCoder )
    ASP.NET Core中的依赖注入(2):依赖注入(DI)
    从零搭建分布式文件系统MinIO比FastDFS要更合适
    WPF : ControlTemplate和DataTemplate的区别
    wpf 中 theme 的使用 和 listview 模板的使用.
    wpf 中的DataTemplate 绑定控件
    HTTP状态码含义
  • 原文地址:https://www.cnblogs.com/edmunds/p/13423744.html
Copyright © 2020-2023  润新知