蓝桥杯2021年第十二届省赛真题-砝码称重
思路
d p [ i ] [ j ] = 1 / 0 dp[i][j] =1/0 dp[i][j]=1/0 : 表示前i个砝码能够凑成重量 j j j
- 如果 j = w [ i ] j=w[i] j=w[i] ,那么 d p [ i ] [ j ] = 1 dp[i][j]=1 dp[i][j]=1
- 否则
- 如果我们看如果不用第 i i i 个砝码,能否凑出重量 j j j: d p [ i − 1 ] [ j ] dp[i-1][j] dp[i−1][j]
- 如果用了第 i i i 个砝码, 要么和第 i i i 个砝码作差凑出 j j j, 要么作和凑出重量 j j j ,: d p [ i − 1 ] [ a b s ( j − w [ i ] ) ] ∣ ∣ d p [ i − 1 ] [ j + w [ i ] ] dp[i-1][abs(j-w[i])] || dp[i-1][j+w[i]] dp[i−1][abs(j−w[i])]∣∣dp[i−1][j+w[i]]。
AC代码
#include<bits/stdc++.h>
#define rep(i,x,y) for(int i=x; i<=y; ++i)
#define per(i,x,y) for(int i=x; i>=y; --i)
#define pushk push_back
#define popk pop_back
#define mem(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define ll long long
#define lp p<<1
#define rp p<<1|1
using namespace std;
const int N = 1e5+9;
int dp[108][N];
int a[N];
int main() {
int n;
cin>>n;
int sum=0;
rep(i,1,n){
scanf("%d",a+i);
sum+=a[i];
//dp[i]
}
// dp[1][0]=1;
rep(i,1,n){
rep(j,0,sum){
if(j==a[i]) dp[i][j]=1;
else dp[i][j]=dp[i-1][j]||dp[i-1][abs(j-a[i])]||dp[i-1][j+a[i]];
}
}
int ans=0;
rep(i,1,sum){
if(dp[n][i]) ans++;
}
cout<<ans<<'\n';
return 0;
}