LOADING

加载过慢请开启缓存,浏览器默认开启

daily 3

2023/4/15 daily

背包专场了属于是

CF 741B

并查集+分组背包
具体不多说了,比较简单

void solve(){
  int n,m,w;
  cin>>n>>m>>w;
  vector<int>dp(w+1),fa(n+1),b(n+1),we(n+1);
  function<int(int x)>f=[&](int x){
        return fa[x]==x?x:fa[x]=f(fa[x]);
  };
  iota(fa.begin(),fa.end(),0);
  for(int i=1;i<=n;++i){
    cin>>we[i];
  }
  for(int i=1;i<=n;++i){
    cin>>b[i];
  }
  for(int i=1;i<=m;++i){
    int u,v;
    cin>>u>>v;
    fa[f(u)]=f(v);
  }
  vector<vector<int>>fr(n+1);
  for(int i=1;i<=n;++i){
    fr[f(i)].push_back(i);
  }
  for(int i=1;i<=n;++i){
    for(int siz=w;siz>=0;--siz){
        int W=0,B=0;
        for(int v:fr[i]){
            W+=we[v];
            B+=b[v];
            if(siz>=we[v])dp[siz]=max(dp[siz-we[v]]+b[v],dp[siz]);
        }
        if(siz>=W){
            dp[siz]=max(dp[siz-W]+B,dp[siz]);
        }
    }
  }
  cout<<dp[w]<<'\n';
  return;
}

CF 19B
我们可以把这个问题转化为01背包,把每个物品看作容量为t[i]+1,代价为c[i]的新物品

void solve(){
  int n;
  cin>>n;
  vector<ll>t(n+1),c(n+1);
  ll w=0;
  for(int i=1;i<=n;++i){
    cin>>t[i]>>c[i];
    ++t[i];
    w=max(t[i],w);
  }
  w+=n;
  vector<ll>dp(w+1,1e16);
  dp[0]=0;
  for(int i=1;i<=n;++i){
    for(int v=w;v>=t[i];--v){
        dp[v]=min(dp[v],dp[v-t[i]]+c[i]);
    }
  }
  ll ans=1e16;
  for(int i=n;i<=w;++i){
    ans=min(ans,dp[i]);
  }
  cout<<ans<<'\n';
  return;
}

CF 577B

没啥好说的了,抽屉原理+dp(甚至感觉都不像背包)

void solve(){
  int n,m;
  cin>>n>>m;
  if(n>m){
    cout<<"YES\n";
    return;
  }
  vector<int>a(n+1);
  for(int i=1;i<=n;++i){
    cin>>a[i];
    a[i]%=m;
  }
  vector dp(m+1,vector<int>(m+1));
  bool f=false;
  for(int i=1;i<=n;++i){
    dp[i][a[i]]=1;
    for(int j=1;j<=m;++j){
        dp[i][j]|=dp[i-1][j];
        dp[i][(j+a[i])%m]|=dp[i-1][j];
    }
    f|=dp[i][0];
    if(f)break;
  }
  cout<<(f?"YES":"NO")<<'\n';
  return;
}