依赖背包TLE3个点求助

P1064 [NOIP2006 提高组] 金明的预算方案

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 好的谢谢谢谢


|