蓝桥杯-12-G-砝码称重

链接:https://www.acwing.com/problem/content/description/3420/

思路:
1:通过分析题目,本题是一个三进制枚举后取正整数的题目,如果直接dfs进行枚举,则时间复杂度为O(3^n),n<=100,时间复杂度不满足条件,但是题目中强调N个砝码总重不超过1e5,也就是结果在[1,1e5]之间,我们可以对n个整数进行遍历枚举与前边已经存在的重量,构成新的重量。时间复杂度为n(1e5)2<2e7,可以通过二维数组进行状态转换。(容易理解)
2:DP,有条件的选择(背包问题),定义f[i][j]为前i个数中选择是否能得到数j,对与f[i][j]时的数numi有三种选择,如果不选则numi f[i][j]=f[i-1][j],如果是加上numi f[i][j]=f[i-1][j-numi],如果是减去numi则f[i][j]=f[i-1][j+numi],分别检查三种情况,如果三种情况任意情况为1则f[i][j]=1,最后计算f[n][j]为1 的个数,由于存在负数情况,加上偏移量即可,最后只计算正整数(题目要求)

思路1代码:

#include<bits/stdc++.h>

using namespace std;
int a[105][(int)1e5+5];
int main (){
    int n,num;
    cin>>n;
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    for(int i=1;i<=n;i++){
        cin>>num;
            for(int j=0;j<=(int)1e5;j++)
                if(a[i-1][j]){
                    a[i][j]=1;
                    a[i][abs(j-num)]=1;
                    a[i][abs(j+num)]=1;
                }
        a[i][num]=1;
    }
    int ans=0;
    for(int i=1;i<=(int)1e5;i++)
        if(a[n][i])ans++;
    cout<<ans;
    return 0;
}

思路2代码:

#include<bits/stdc++.h>


using namespace std;
int f[105][(int)2e5+5],m=(int)1e5;//m是偏移量,f[0][m]本质为f[0][0]
int main (){
    f[0][m]=1;//初始化 
    int n,num;
    cin>>n;
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
   
    for(int i=1;i<=n;i++){
        cin>>num;
        for(int j=0;j<=(int)2e5;j++){
            f[i][j]=f[i-1][j];
            if(j+num<=(int)2e5)f[i][j] |= f[i-1][j+num];//注意这里是 或运算
            if(j-num>=0)f[i][j] |= f[i-1][j-num];//只要这三种有一个为1 则f[i][j]=1;
        }
    }
    int ans=0;
    for(int i=1;i<=(int)1e5;i++)
        if(f[n][i+m])ans++;
    cout<<ans;
    return 0;
}
上一篇:C++多继承导致的菱形继承问题


下一篇:CF 1110E