社区讨论
如果这个题没有m>=n-2的限制……
P6775[NOI2020] 制作菜品参与者 1已保存回复 2
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @mlgxy2dz
- 此快照首次捕获于
- 2026/02/11 02:35 4 周前
- 此快照最后确认于
- 2026/02/11 02:35 4 周前
能做的最优复杂度多少?
我纯口糊了个做法,不知道对不对。
首先,若 则一定无解。
对于 的情况,假设 。
就是要拆成 个 满足 。
朴素的,按 的方法拆出来一个 ,剩下的就是 的情况。拆 次即可。
但这样是 的。
如果拆完第一次,拆下一次时,不同“朴素的”一样再做一遍背包,而是再利用已经求出的背包结果。
下面是我 的代码。
CPP dp[0].reset();
dp[0][n*k]=1;
for(int i=1;i<=n;i++){
if(d[i]-k>=0){
dp[i]=dp[i-1]|(dp[i-1]<<d[i]-k);
}else{
dp[i]=dp[i-1]|(dp[i-1]>>k-d[i]);
}
}
if(!dp[n][n*k-k]){
cout<<"-1\n";
return;
}
set<PII>st1,st2;
for(int i=n,val=n*k-k;i>=1;i--){ //拆第一次,由于m=n-2,所以只拆这一次
if(dp[i-1][val-(d[i]-k)]){
val-=d[i]-k;
st1.insert(mkp(d[i],i)); //一个m=n-1的集合
}else{
st2.insert(mkp(d[i],i)); //其他的,由于m=n-2,所以亦满足m=n-1
}
}
work(st1),work(st2); //处理m=n-1的
拆第一次时,是从 出发往前推(代码中离散化成 了),从而拆出一个 的集合 。
拆第二次时,若从 出发往前推,是不是能拆出一个 的集合 ?
若使 ,那么 是不是就是与 不相交的另外一个 的集合了?补集咋打啊……
这个不用每次都跑一边背包,复杂度是 的?其中拆 次 ,拆一次 。
回复
共 2 条回复,欢迎继续交流。
正在加载回复...