https://www.luogu.com.cn/record/102157012
题解:
1.定义数组dp数组含义:dp[i]表示的是以 i 为结果的重量是否出现过;
2.找规律: 只有当 k 为质量的结果出现过,才能标记 k+w[i];
if(dp[k]==1&&k+w[i]<=1000) dp[k+w[i]]=1;
3.初始化:dp[0]=1;一个砝码都不用是可以理论上是可以成立的;但由于题目要求不包括一个砝码都不用的情况,所以最后找不同质量的个数的时候要从下标1开始。
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdlib.h>
using namespace std;
int w[7]={0,1,2,3,5,10,20};//单个砝码质量
int a[7];//砝码数量
const int N=1e3+10;
int dp[N];
int main()
{
dp[0]=1;
for(int i=1;i<=6;i++)
scanf("%d",&a[i]);
for(int i=1;i<=6;i++)//单个砝码的质量
{
for(int j=1;j<=a[i];j++)//循环砝码的个数
{
for(int k=1000;k>=0;k--)//砝码的总质量小于1000,所以这是最大的价值
{
if(dp[k]==1&&k+w[i]<=1000)//只有当k为质量的结果出现过,才能标记k+w[i]
{
dp[k+w[i]]=1;
}
}
}
}
int cnt=0;
for(int i=1;i<=1000;i++)//从1开始找个数
{
if(dp[i]==1)
cnt++;
}
printf("Total=%d\n",cnt);
return 0;
}
https://www.luogu.com.cn/record/102165192
题解:
1.定义数组dp的含义:d[i][j]表示的是第 i-1 个砝码是达到的 j 重量;
2.找规律:
如果 i-1 个砝码已经到达 j 质量并且标记过:if (dp[i-1][j])
- 选择不放第 i 个砝码:dp[i][j] = d[i-1][j];
- 选择将第 i 个砝码放右边,所以总重量增加: dp[i][j + a[i]] = 1
- 选择第 i 个砝码左边放在左边,此时 j 的质量是左右相差的绝对值:dp[i][abs(j - a[i])] = 1;
特殊情况:如果第 i 个砝码和 j 的重量相等,由于可以只放一个砝码,所以此时的 dp[i][j]=1;
3.初始化:dp[0]=1;一个砝码都不用是可以理论上是可以成立的;但由于题目要求不包括一个砝码都不用的情况,所以最后找个数倒着找到下标为1就要结束;
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
const int N=1e2+10;
const int M=1e5+10;
int dp[N][M],a[M];
int n,sun=0,cn;
int main()
{
scanf("%d",&n);
int sum=0;
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
sum+=a[i];//砝码的总价值
}
dp[0][0]=1;
for(int i=1; i<=n; i++)
{
for(int j=sum; j>=0; j--)
{
if (dp[i-1][j])//如果 i-1 个砝码已经到达 j 质量并且标记过
{
dp[i][j] = 1;//选择不放第 i 个砝码
dp[i][j + a[i]] = 1;//选择将第 i 个砝码放右边
dp[i][abs(j - a[i])] = 1;
//选择第 i 个砝码左边放在左边,此时 j 的质量是左右相差的绝对值
}
if(a[i]==j)
dp[i][j]=1;
}
}
int cnt=0;
for(int i=sum; i>=1; i--)//找个数
{
if(dp[n][i]==1)
cnt++;
}
printf("%d\n",cnt);
return 0;
}