读题可以发现是分组背包问题,但是要求每个组别至少用上一个,所以调用的前一种状态必须是已经含有前一组的物品,打个标记即可。
#include <bits/stdc++.h>
using namespace std;
const int N=501;
int n,m,c,w[N],t[N],f[N][10001];
bool use[N][10001];
vector<int>a[N];
int main(){
cin>>n>>m>>c;
for(int i=1;i<=n;++i)
cin>>w[i];
for(int i=1;i<=n;++i)
cin>>t[i];
for(int i=1;i<=n;++i){
a[t[i]].push_back(w[i]);
}
for(int j=1;j<=c;++j)
use[0][j]=true;
for(int i=1;i<=m;++i){
for(int j=1;j<=c;++j){
for(auto k:a[i]){
if(j-k>=0 and use[i-1][j-k]){//本组的当前物品可以拿,并且前一组对应状态是拿过的
if(f[i-1][j-k]+k>f[i][j]){//拿了,并且更大,标记一下
f[i][j]=f[i-1][j-k]+k;
use[i][j]=true;
}else//拿不了,继承当前组的状态
f[i][j]=f[i][j-1];
}
}
}
}
cout<<f[m][c];
return 0;
}
代码不知道对不对,只能过样例,本蒟蒻比赛的前一天没睡觉,导致while(true)rp--
提醒各位千万不要在考试或者比赛之前熬夜或者通宵((((
下面放一个时间超时的递归代码。
#include <bits/stdc++.h>
using namespace std;
const int N=501;
int n,m,c,w[N],t[N],ans;
bool vis[N];
void dfs(int now,int weight,int cnt){
if(now==n+1)return;
if(weight>c)return;
if(cnt==m)ans=max(ans,weight);
if(!vis[t[now+1]]){
vis[t[now+1]]=true;
dfs(now+1,weight+w[now+1],cnt+1);
vis[t[now+1]]=false;
}
dfs(now+1,weight,cnt);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
cin>>n>>m>>c;
for(int i=1;i<=n;++i)
cin>>w[i];
for(int i=1;i<=n;++i)
cin>>t[i];
dfs(0,0,0);
cout<<ans;
return 0;
}