rt,我在写这一题的时候,使用了分治写法。但是我把最优决策点初始化为不一样的,分数也不一样,请问这是为什么?或者说什么写法是对的?
AC:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,k,vmx = 0,rdmod,best;
vector<int>newitem[300005];
struct node {
int c,v;
}a[5000005];
int mdp[5000005],dp[5000005],fmdp[5000005];
int w(int mod,int r) {return newitem[mod][r];}
void solve(int l,int r,int pl,int pr) {
if(l > r) return ;
int mid = (l + r) >> 1;
int qt = mid;
mdp[mid] = fmdp[mid];
for(int pos = pl;pos <= pr && pos < mid;++pos){
if(mid - pos > newitem[rdmod].size()) continue;//判出界!!!!!
if(mdp[mid] <= fmdp[pos] + w(rdmod,mid - pos - 1)) qt = pos,mdp[mid] = max(fmdp[pos] + w(rdmod,mid - pos - 1),mdp[mid]);
}
if(l == r) return ;
solve(l,mid - 1,pl,qt);
solve(mid + 1,r,qt,pr);
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
// freopen("jewelry18.in","r",stdin);
// freopen("jewelry20.out","w",stdout);
cin >> n >> k;
for(int i = 1;i <= n;++i) cin >> a[i].c >> a[i].v,newitem[a[i].c].push_back((int)a[i].v),vmx = max(vmx,a[i].c);
for(int i = 1;i <= vmx;++i) {
if(newitem[i].empty()) continue;
sort(newitem[i].begin(),newitem[i].end(), greater<int>() );
for(int j = 1;j < (int)newitem[i].size();++j) newitem[i][j] += newitem[i][j - 1];
}
for(int i = 1;i <= vmx;++i) {
if(newitem[i].empty()) continue;
rdmod = i;
for(int mod = 0;mod < i;++mod) {
int tot = 0;
for(int j = mod;j <= k;j += i) fmdp[++tot] = dp[j];//上一次的dp
//j:同余的体积
solve(1,tot,1,tot);
//分治的实际上是同余的体积,分治的是倍数
for(int j = 1,wl = mod;wl <= k;wl += i,++j) dp[wl] = mdp[j];
//j:枚举的是mod+c_i*j中的j倍
}
}
for(int j = k;j >= 1;--j) dp[j] = max(dp[j],dp[j - 1]);
for(int i = 1;i <= k;++i) cout << dp[i] << " ";
cout << '\n';
return 0;
}
WA:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,k,vmx = 0,rdmod,best;
vector<int>newitem[300005];
struct node {
int c,v;
}a[5000005];
int mdp[5000005],dp[5000005],fmdp[5000005];
int w(int mod,int r) {return newitem[mod][r];}
void solve(int l,int r,int pl,int pr) {
if(l > r) return ;
int mid = (l + r) >> 1;
int qt = pl;//只有这里不一样
mdp[mid] = fmdp[mid];
for(int pos = pl;pos <= pr && pos < mid;++pos){
if(mid - pos > newitem[rdmod].size()) continue;//判出界!!!!!
if(mdp[mid] <= fmdp[pos] + w(rdmod,mid - pos - 1)) qt = pos,mdp[mid] = max(fmdp[pos] + w(rdmod,mid - pos - 1),mdp[mid]);
}
if(l == r) return ;
solve(l,mid - 1,pl,qt);
solve(mid + 1,r,qt,pr);
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
// freopen("jewelry18.in","r",stdin);
// freopen("jewelry20.out","w",stdout);
cin >> n >> k;
for(int i = 1;i <= n;++i) cin >> a[i].c >> a[i].v,newitem[a[i].c].push_back((int)a[i].v),vmx = max(vmx,a[i].c);
for(int i = 1;i <= vmx;++i) {
if(newitem[i].empty()) continue;
sort(newitem[i].begin(),newitem[i].end(), greater<int>() );
for(int j = 1;j < (int)newitem[i].size();++j) newitem[i][j] += newitem[i][j - 1];
}
for(int i = 1;i <= vmx;++i) {
if(newitem[i].empty()) continue;
rdmod = i;
for(int mod = 0;mod < i;++mod) {
int tot = 0;
for(int j = mod;j <= k;j += i) fmdp[++tot] = dp[j];//上一次的dp
//j:同余的体积
solve(1,tot,1,tot);
//分治的实际上是同余的体积,分治的是倍数
for(int j = 1,wl = mod;wl <= k;wl += i,++j) dp[wl] = mdp[j];
//j:枚举的是mod+c_i*j中的j倍
}
}
for(int j = k;j >= 1;--j) dp[j] = max(dp[j],dp[j - 1]);
for(int i = 1;i <= k;++i) cout << dp[i] << " ";
cout << '\n';
return 0;
}