2023首届大学生算法大赛 - 拿饼干


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

#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;
}

猜你喜欢

转载自blog.csdn.net/qq_17807067/article/details/129920336