资源限制
时间限制:1.0s 内存限制:256.0MB
本题是我做不出的一道题,也是网上搜了题解才明白的,该题的解决办法是 dp
我们分三步走
首先定义一个dp数组根据题意我们定义一个二维数组dp[i][j]涵义为前i个砝码可以称出质量j
其次,我们需要找到数组元素之间的关系表达式,我们这样想,如果前i个砝码可以称出质量j
,那么会与dp[ i-1 ][ j ]或者其他元素有什么关系呢??? (这里有些难)
我们假设在能够使用前 i 个砝码称出质量 j 的情况下,那么必然在放下那最后第 i 个砝码的时候,我们会面临以下三种选择
- 放在天平左边
- 放在天平右边
- 不放
在这三种选择下,为了得到质量 j ,我们必然会得到与之相对应的结果
在上面这样的角度思考,我们便能更好地理解
dp[i][j] = dp[i - 1][abs(j - w[i])] + dp[i - 1][j + w[i]] +dp[i - 1][j]
第三步是初始化dp[0][0] = 1;//前0件可以称出重量为0
下面请看代码
#include<bits/stdc++.h> using namespace std; typedef long long ll; int dp[102][100005]={0};//定义dp[i][j]涵义为前i个砝码可以称出质量j int w[102]; int n; int sum = 0; int main() { scanf("%d",&n); for (int i = 1; i <= n; i++) { scanf("%d",&w[i]); sum += w[i]; } dp[0][0] = 1;//前0件可以称出重量为0 for (int i = 1; i <= n; i++) { //有n*sum个状态 for (int j = 0; j <= sum; j++) {//这里j不能从1开始 必须从0 第一件物品不可能称出0 但是前i件可能称出0 dp[i][j] = dp[i - 1][abs(j - w[i])] + dp[i - 1][j + w[i]] +dp[i - 1][j]; } //这里表达式的意思是 能否用前i个砝码称出质量j,取决于我们要放的砝码w[i]放在左边或者右边或者不放 } //的时候能否称出“对应 ”的质量 int ans = 0; for (int i = 1; i <= sum; i++) { if (dp[n][i] != 0) {//能使用前n个砝码称出质量i ans++; } } printf("%d",ans); return 0; }