#include<bits/stdc++.h>
using namespace std;
int n,k,s; 
int a[505];
int c[505];
int dp[250005];
int main(){
	cin>>n>>k;
	
	for(int i=1;i<=n;i++){
		cin>>a[i]>>c[i];
		s+=a[i]; 
	}for(int i=1;i<=s;i++){
		dp[i]=2e9+100;
	} 
	for(int i=1;i<=n;i++){
		for(int j=s;j>=a[i];j--){
			dp[j]=min(dp[j],c[i]+dp[j-a[i]]);
		}
	}int maxn=0;
	for(int i=0;i<=s;i++){
		if(dp[i]<=k){
			maxn=i;
		}
	}cout<<maxn;
	return 0;
}

2 条评论

  • @ 2026-9-12 7:46:25

    关键信息:k 高达 1e9,但 aᵢ ≤ 500,n ≤ 500,所以总攻击力 s = Σaᵢ ≤ 250000。

    这题不能按「金币 k」做容量(太大),要反过来:把攻击力当作容量,求达到每个攻击力所需的最小金币数。

    你的代码问题

    你的 dp 定义其实是 对的方向(dp[j] = 达到攻击力 j 的最小金币),但有一个逻辑错误:

    for(int j=s;j>=a[i];j--)
        dp[j]=min(dp[j],c[i]+dp[j-a[i]]);
    

    这是 01 背包的倒序写法 —— 而本题「每件道具只能购买一次」,正是 01 背包,所以倒序 ✅ 没错。

    所以你的代码逻辑基本正确!问题在细节:

    ⚠️ 问题 1:INF 溢出

    dp[i] = 2e9 + 100;   // 2147483747
    

    dp[j-a[i]] 若是 INF,加 c[i](可达 1e9)→ 溢出 int,得到负数,导致错误答案。

    改成 0x3f3f3f3f(约 1.06e9)或直接用 1e18 配 long long:

    const int INF = 0x3f3f3f3f;
    

    ⚠️ 问题 2:c[i] 是 1e9 级别,dp 值可能超 int?

    dp[j] 最大是「买一堆道具的总金币」,理论上可达 n×1e9 = 5e11,会溢出 int!

    但由于我们只关心 dp[j] <= k (1e9),一旦超过就可以当「不可达」。用 long long 更安全:

    long long dp[250005];
    

    ⚠️ 问题 3:找答案的循环

    for(int i=0;i<=s;i++)
        if(dp[i]<=k) maxn=i;
    

    正序 + 不 break,效率低。倒序找到就停:

    for(int i=s;i>=0;i--)
        if(dp[i]<=k){ cout<<i; break; }
    

    ✅ 修正版

    #include<bits/stdc++.h>
    using namespace std;
    const long long INF = 1e18;
    int n, k, s;
    int a[505], c[505];
    long long dp[250005];
    int main(){
        cin >> n >> k;
        for(int i=1;i<=n;i++){
            cin >> a[i] >> c[i];
            s += a[i];
        }
        fill(dp, dp+s+1, INF);
        dp[0] = 0;
        for(int i=1;i<=n;i++)
            for(int j=s;j>=a[i];j--)
                dp[j] = min(dp[j], c[i] + dp[j-a[i]]);
        for(int i=s;i>=0;i--)
            if(dp[i] <= k){ cout << i; break; }
        return 0;
    }
    

    复杂度

    · 时间:O(n·s) = 500 × 250000 = 1.25e8,能过(GESP 一般 1s 内,稍紧但可接受) · 空间:250005 × 8 ≈ 2MB,OK

    一句话总结

    你的思路正确,倒序也对(每件只能买一次 = 01 背包)。核心 bug 是 INF 用 2e9+100 会溢出,改 0x3f3f3f3f 或换 long long 即可。

    • @ 2026-9-6 14:52:44

      受着

    • 1

    信息

    ID
    2650
    时间
    ms
    内存
    MiB
    难度
    3
    标签
    递交数
    76
    已通过
    14
    上传者