小M和天平 题解(背包)

题目链接

题目思路

注意石子可以摆到两边

则一个石子可以为a[i] 0 -a[i]

则背包直接背就行

把初始重量直接变成1e4

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e2+5;
int n,k;
int a[maxn];
int dp[maxn][20000+500];
int main(){
    int mid=1e4;
    while(scanf("%d",&n)!=-1){
        int ma=0;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            ma+=a[i];
        }
        dp[0][mid]=1;
        for(int i=1;i<=n;i++){// a[i] -a[i] 0
            for(int j=mid-ma;j<=mid+ma;j++){
                if(dp[i-1][j]){
                    dp[i][j]=dp[i][j+a[i]]=dp[i][j-a[i]]=1;
                }
            }
        }
        int _;scanf("%d",&_);
        while(_--){
            scanf("%d",&k);
            printf((k<=1e4&&dp[n][k+mid])?"YES\n":"NO\n");
        }
        for(int i=1;i<=n;i++){// 
            for(int j=mid-ma;j<=mid+ma;j++){
                dp[i][j]=0;
            }
         }
    }
    return 0;
}

还有一种方法其实-a[i] 就等于\(f[i][abs(j-a[i])]\)

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e2+5;
int n,k;
int a[maxn];
int dp[maxn][10000+500];
int main(){
    while(scanf("%d",&n)!=-1){
        int ma=0;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            ma+=a[i];
        }
        dp[0][0]=1;
        for(int i=1;i<=n;i++){// 
            for(int j=0;j<=ma;j++){
                if(dp[i-1][j]){
                    dp[i][j]=dp[i][j+a[i]]=dp[i][abs(j-a[i])]=1;
                }
            }
        }
        int _;scanf("%d",&_);
        while(_--){
            scanf("%d",&k);
            printf((k<=1e4&&dp[n][k])?"YES\n":"NO\n");
        }
        for(int i=1;i<=n;i++){// 
            for(int j=0;j<=ma;j++){
                dp[i][j]=0;
            }
         }
    }
    return 0;
}

posted @ 2021-01-24 20:59  hunxuewangzi  阅读(79)  评论(0编辑  收藏  举报