zoukankan      html  css  js  c++  java
  • 小A点菜

    传送门

    思路(1)

    十分经典的一道DP题。
    转移方程式为:

    f[j]+=f[j-a[i]];
    

    我们首先定义(f[i][j])表示前(i)个菜品恰好花费(j)元的方案数。
    当我们买第(i)道菜时:

    f[i][j]+=f[i-1][j-a[i]];
    

    当我们不买第(i)道菜时:

    f[i][j]+=f[i-1][j];
    

    但当第(i)道菜的价格被就是(j)时,就可以只买自己,这种情况应该其实包含在(1)中,但是由于(f[i][0]=0),所以不会算入这种情况。所以我们就要把(f[i][0])刚开始就赋值为(1)
    代码

    #include <bits/stdc++.h>
    using namespace std;
    int n,m,a[105],f[105][10005];
    
    int main() {
    	scanf("%d %d",&n,&m);
    	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    	for(int i=0;i<=n;i++) f[i][0]=1;//注意0 
    	for(int i=1;i<=n;i++) {
    		for(int j=1;j<=m;j++) {
    			f[i][j]+=f[i-1][j];
    			if(j>=a[i]) f[i][j]+=f[i-1][j-a[i]];
    		}
    	}
    	printf("%d",f[n][m]);
    	return 0;
    }
    

    我们可以优化为一维。
    但我们的第二重循环必须逆序跑,因为我们一维的转移方程式为:

    f[j]+=f[j-a[i]];
    

    如果跑正序,我们的(f[j])还没有更新,(f[j-a[i]])反倒先更新了,这样的话与题意的“每种菜只有一份”相冲。如果没有这句话,我们就可以正序了。

    #include <bits/stdc++.h>
    using namespace std;
    int n,m,a[105],f[10005];
    
    int main() {
    	scanf("%d %d",&n,&m);
    	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    	f[0]=1; 
    	for(int i=1;i<=n;i++) {
    		for(int j=m;j>=a[i];j--)
    			f[j]+=f[j-a[i]];
    	}
    	printf("%d",f[m]);
    	return 0;
    }
    

    思路(2)

    ((1)if(j==第i道菜的价格) f[i][j]=f[i-1][j]+1;)

    ((2)if(j>第i道菜的价格) f[i][j]=f[i-1][j]+f[i-1][j-第i道菜的价格];)

    ((3)if(j<第i道菜的价格) f[i][j]=f[i-1][j];)

    说的简单一些,这三个方程,每一个都是在吃与不吃之间抉择。若钱充足,办法总数就等于吃这道菜的办法数与不吃这道菜的办法数之和;若不充足,办法总数就只能承袭吃前(i-1)道菜的办法总数。依次递推,在最后,我们只要输出(f[n][m])的值即可。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    int n,m,a[105],f[105][10005];
    
    int main() {
    	scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<=n;i++) {
        	for(int j=1;j<=m;j++) {
    			if(j==a[i])f[i][j]=f[i-1][j]+1;
            	else if(j>a[i]) f[i][j]=f[i-1][j]+f[i-1][j-a[i]];
            	else f[i][j]=f[i-1][j];
        	}
    	}
    	printf("%d",f[n][m]);
        return 0;
    }
    
  • 相关阅读:
    设计模式:Prototype 原型模式
    [C++STDlib基础]关于单字符的操作——C++标准库头文件<cctype>
    Android开发之简单的电子相册实现
    autotools入门笔记(二)——创建和使用静态库、动态库
    Dreamer 框架 比Struts2 更加灵活
    Redis集群明细文档
    【Servlet3.0新特性】第03节_文件上传
    POJ 3264 Balanced Lineup
    利用jquery对ajax操作,详解原理(附代码)
    C语言实现修改文本文件中的特定行
  • 原文地址:https://www.cnblogs.com/sxqn/p/13973873.html
Copyright © 2011-2022 走看看