BZOJ5281 [Usaco2018 Open]Talent Show(01分数规划+背包)

原题

挂个链接BZOJ

Solution

分析:

显然我们可以直接\(01\)分数+\(dp\)然后就AC了...

注意一下\(dp\)的更新方式.

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<queue>
#include<algorithm>
#define ll long long
#define re register
using namespace std;
inline int gi(){
  int sum=0,f=1;char ch=getchar();
  while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
  while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
  return f*sum;
}
inline ll gl(){
  ll sum=0,f=1;char ch=getchar();
  while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
  while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
  return f*sum;
}
const double eps=1e-6;
int n,W,w[310],t[310];
double s[310],dp[310][1020];
bool check(double mid){
  dp[0][0]=0;
  for(re int i=1;i<=n;i++)s[i]=t[i]-mid*w[i];
  for(re int i=1;i<=n;i++)
    for(re int j=0;j<=W;j++){
      dp[i][j]=max(dp[i][j],dp[i-1][j]);
      dp[i][min(W,j+w[i])]=max(dp[i][min(W,j+w[i])],dp[i-1][j]+s[i]);
      
    }
  return dp[n][W]>=0;
}
int main(){
  n=gi();W=gi();
  for(re int i=1;i<=n;i++)
    w[i]=gi(),t[i]=gi();
  double l=0,r=1e6;
  while(r-l>eps){
    double mid=(l+r)/2;
    for(re int i=0;i<=n;i++)
      for(re int j=0;j<=W;j++)
    dp[i][j]=-1e18;
    if(check(mid))l=mid;
    else r=mid;
  }
  printf("%d\n",(int)(l*1000));
  return 0;
}

猜你喜欢

转载自www.cnblogs.com/cjgjh/p/9769497.html
今日推荐