UT_MC_wuming @ 2024-07-21 16:35:56
rt,#7,8,9TLE了其他AC
#include <bits/stdc++.h>
using namespace std;
const int maxx=32005;
typedef int ll;
ll T,M,c[65],va[65],dp[maxx]={},w[65];//c花费,v重要度,w所求乘积
//dp[k]表示前k组最优解
vector<ll>vice[65],chief;//分组
bool vis[65];
ll dp1[61][maxx]={};
int limit[65];
int main() {
scanf("%d%d",&T,&M);
int p=0;
for(int i=1; i<=M; i++) {
scanf("%d%d%d",&c[i],&va[i],&p);
w[i]=c[i]*va[i];
if(p!=0)vice[p].push_back(i);
else {
chief.push_back(i);
vis[i]=true;
}
}
//先把有副的以主为根跑一遍01背包
//分组并将每一组转化为(V-c[i]+1)个物品的物品组
int si=chief.size();
//cout<<chief[0]<<endl;
for(int i=0; i<si; i++) {
int tem=chief[i];
for(int j=c[tem]; j<=T; j++)dp1[tem][j]=w[tem]; //主机每组都必须买(主机cost在分组计算时+)
/*if(vice[tem].empty()){
limit[tem]=
}*/
for(int j=0; j<vice[tem].size(); j++) {//枚举每种附件
for(int k=T;k>=c[vice[tem][j]]+c[tem];k--){
dp1[tem][k]=max(dp1[tem][k],dp1[tem][k-c[vice[tem][j]]]+w[vice[tem][j]]);
}
}
}
/*for(int i=1;i<=M;i++){
for(int j=0;j<T;j++){
cout<<dp1[i][j]<<" ";
}cout<<endl;
}*/
//再以每个主及副为一组
for(int k=1; k<=M; k++) {
if(vis[k]) {//为主件
//int tem=chief[k];nb
for(int v=T; v>=c[k]; v--) {
//if(!vice[k].empty()) {
for(int i=v; i>=c[k]; i--) {
dp[v]=max(dp[v],dp[v-i]+dp1[k][i]);
//if(dp1[k][i]==c[k])break;剪枝,但交上去又多一个TLE)因为break之前114514次循环都要判断的)
}//cout<<k<<" "<<dp[T]<<endl;
//}
}
}
}printf("%d",dp[T]);
return 0;
}
没看题解自己打的
一开始没看到说附件<=2个所以写复杂了
有大佬能来降下时间复杂度吗谢谢
by Obijeb @ 2024-07-21 16:54:50
将所有有关价格的变量都除以10即可 @UT_MC_wuming
by Obijeb @ 2024-07-21 16:55:51
题中给出所有价格都是10的倍数
可以将价格和钱数同除10
再将最终的答案*10
by UT_MC_wuming @ 2024-07-21 17:28:04
@Obijeb 感谢感谢!现在AC了!
请问大佬为什么可以这样啊?
by Obijeb @ 2024-07-21 18:51:59
@UT_MC_wuming ?
价格是10的倍数是题面给出的,所以可以用类似提公因数的方式化简,最后再乘上10就行了
新的价格和钱都是原来的十分之一
这样计算出的最终答案中,价格变为十分之一,重要度不变,故两者乘积变为十分之一
如果还有不懂建议优先翻题解
by UT_MC_wuming @ 2024-07-21 20:06:58
@Obijeb 好的谢谢谢谢