读题可以发现是分组背包问题,但是要求每个组别至少用上一个,所以调用的前一种状态必须是已经含有前一组的物品,打个标记即可。
#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;
}