动态规划入门(一)

问题A
题目描述
给你n个钱币,去一个不找钱的商场买东西,你可以买多少种价格的物品?

输入
第一行:一个整数n,范围在[0, 100]。
第二行:n个整数,每个数范围在[1, 100]

输出
可能买的不同价格数。(包括价格0)

样例输入

3
3 2 2

样例输出

6

提示
【样例解释】:
0,2,3,4(2+2),5(2+3),7(2+2+3)

【题目分析】
要想知道刚刚好n元可以有多少种搭配,就得知道n可以由哪几个物品得来,以及购买i元的方案数…简单来说就是上一步方案数的累加。
【AC代码】

#include
using namespace std;
int n,ans;
int a[105],b[105][20005];
int main(){
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    b[0][0]=1;//初始化
    for(int i=1;i<=n;i++){
        for(int j=0;j<10001;j++)if(b[i-1][j]!=0)b[i][j+a[i]]=1;//统计答案
        //b[i][j]意思是第i个物品价值j有没有达到(我自己很难解释。。。)
        for(int j=0;j<10001;j++)if(b[i-1][j]!=0)b[i][j]=1;//同上
    }
    for(int i=0;i<10001;i++)ans+=b[n][i];//算出最终答案
    cout<<ans;
    return 0;
}

【注意】别忘了初始化哦

问题B
题目描述
给你n个正整数,每个数可选或不选,问可以选一些数它们的和可以生成多少100以内的不同数?

输入
第一行:一个整数n,范围在[0, 100000]。
第二行:n个整数,每个数范围在[1, 10000]。

输出
可生成数。(包括0和100)

样例输入

3
30 50 100

样例输出

5

提示
【样例解释】:
0,30,50,80,100。

【题目分析】
要想知道可不可以生成第i个数,就得先知道第i个数由哪两个数相加得来。并累加前面的答案,即为最终答案。

【AC代码】

#include
using namespace std;
int n,ans,a;
int b[100005];
int main()
{
    cin>>n;
    b[0]=1;//初始化
    for(int i=1;i<=n;i++)
    {
        cin>>a;
        for(int j=100;j>=0;j--)//一维要从大到小,以免重复
        	if(b[j]!=0)b[j+a]=1;//判断能否到达j+a(前提是当前j是存在的,亦或者说是i为到达过的值)
    }
    for(int i=0;i<101;i++)ans+=b[i];//累加,算出最终答案
    cout<<ans;
    return 0;
}

问题C

题目描述
给你n个正整数,每个数可选或不选,要求选一些数,使它们的和为100,问有多少种方案?

输入
第一行:一个整数n,范围在[1, 100000]。
第二行:n个整数,每个数范围在[1, 10000]。

输出
方案数。(答案不超过2^63)

样例输入

6
30 50 100 70 30 40

样例输出

4

提示
【样例解释】:
30+70, 30+30+40,100,70+30。

【题目分析】
这一题与第1题有点相似,又与上一题颇为相似。只是特定了最后答案的位置,要想知道到达100的方案数,就必须知道之前的方案数,以此类推。最后的答案就在b[100]里面。

【AC代码】

#include
using namespace std;
int n,a;
int b[10005];
int main(){
    cin>>n;
    b[0]=1;//初始化
    for(int i=1;i<=n;i++){
        cin>>a;
        if(a>100)continue;//判断是不是需要的数字
        for(int j=200;j>=0;j--)if(b[j]!=0)b[j+a]++;//同上一题差不多,只是要;累加,统计方案数
    }
    cout<<b[100];//最终答案
    return 0;
}

【问题D】

题目描述
给你n个正整数,每个数可选或不选,要求选一些数,使它们的和为S,输出任意一种方案。

输入
第一行:2个整数n的范围在[1, 10000],s的范围在[1, 1000000]。
第二行:n个整数,每个数范围在[1, 1000]。

输出
输出任意一种方案。如果没有方案,输出-1。

样例输入

6 110
30 50 100 70 30 40

样例输出

30 50 30

提示
样例解释:
或者 70 40也可以。

【题目分析】

这题就是更改一下上一题,记录方案以及记录路径!(重难点)然后就没什么难度了。

【AC代码】

#include
using namespace std;
long long n,a,s;
long long fa[1000005],b[1000005];
int main()
{
    cin>>n>>s;
    b[0]=1;//初始化
    for(int i=1;i<=n;i++){
        cin>>a;
        if(a>s)continue;//判读是不是需要的数
        for(int j=s;j>=0;j--)
        {
            if(b[j]!=0&&!fa[j+a])//判断这个数可不可以用以及是否可以更新路径
            {
                b[j+a]++;//计算方案
                fa[j+a]=a;//记录路径
            }
        }
    }
    if(b[s]==0)//答案是否有解
    {
        cout<<-1;
        return 0;
    }
    while(s!=0)//输出路径
    {
        cout<<fa[s]<<" ";
        s-=fa[s];//更新下标
    }
    return 0;
}

问题E、F本蒟蒻还未解出,望各位大佬帮忙。

【问题E】
题目描述
给你n个整数,每个数可选或不选,要求选一些数,使它们的和为S,问有多少种方案?

输入
第一行:2个整数n和s,范围都在[1, 100]。
第二行:n个整数,每个数范围在[-100, 100]

输出
输出方案数。(答案不超过2^63)

样例输入

6 10
3 4 7 8 -1 2 

样例输出

4

提示
【样例解释】:
3+7, 3+8-1, 4+7-1, 8+2

【问题F】

题目描述
给你n个正整数,要求你分成2堆,使它们各自的和尽量相同。问2堆的差距最小是多少?

输入
第一行:1个整数n,范围都在[1, 1000]。
第二行:n个整数,每个数范围在[1, 100]

输出
输出最小差距。

样例输入

7 
3 4 7 8 21 27 100

样例输出

30

提示
【样例解释】:
70=3+4+7+8+21+7
30=100-70

以上就是全部了,第一次写博客,菜!

你可能感兴趣的:(动态规划入门(一))