#include <stdio.h>
int n, m, i, j, k, c, v, f[10005];
int main(){
    scanf("%d%d", &n, &m);
    f[0] = 1;
    for(i=1; i<=n; i++){
        scanf("%d%d", &v, &c);
        while(c--){
            for(j=m; j>=v; j--){
                f[j] |= f[j-v];
            }
        }//拆分乘c个01背包
    }//多重背包模板
    printf("%s\n", f[m]?"Yes":"No");
    return 0;
}

记忆化搜索做法:

#include <stdio.h>
int n, m, i, j, k, ok;
int a[55], c[55], f[55][10005];
void dfs(int k, int s){
    int i, j;
    if(s == m) ok = 1;
    if(ok) return;
    if(s > m) return;
    if(k > n) return;
    if(f[k][s]) return;
    f[k][s] = 1;//记忆化
    for(i=0; i<=c[k]; i++){
        dfs(k+1, s+i*a[k]);
    }//暴力枚举每种面额用多少个 
}
int main(){
    scanf("%d%d", &n, &m);
    for(i=1; i<=n; i++){
        scanf("%d%d", &a[i], &c[i]);
    }
    dfs(1, 0);
    printf("%s\n", ok?"Yes":"No");
    return 0;
}

作者 crxis

发表回复