zoukankan      html  css  js  c++  java
  • 洛谷 P1164:小A点菜(DP/DFS)

    题目背景

    uim神犇拿到了uoira(镭牌)后,立刻拉着基友小A到了一家……餐馆,很低端的那种。

    uim指着墙上的价目表(太低级了没有菜单),说:“随便点”。

    题目描述

    不过uim由于买了一些辅(e)辅(ro)书,口袋里只剩 MM 元 (M le 10000)(M≤10000) 。

    餐馆虽低端,但是菜品种类不少,有 NN 种 (N le 100)(N≤100) ,第 ii 种卖 a_iai​ 元 (a_i le 1000)(ai​≤1000) 。由于是很低端的餐馆,所以每种菜只有一份。

    小A奉行“不把钱吃光不罢休”,所以他点单一定刚好吧uim身上所有钱花完。他想知道有多少种点菜方法。

    由于小A肚子太饿,所以最多只能等待 11 秒。

    输入输出格式

    输入格式:

    第一行是两个数字,表示 N和 M 。

    第二行起 N个正数 ai​ (可以有相同的数字,每个数字均在 10001000 以内)。

    输出格式:

    一个正整数,表示点菜方案数,保证答案的范围在 int 之内。

    输入输出样例

    输入样例#1: 复制

    4 4
    1 1 2 2
    

    输出样例#1: 复制

    3

    思路

    • DP:好像是01背包的变形(看到好多大佬都是这样说)。用dp数组来记录拿到总价值数为j时的方案数(我是这样理解的,把dp过程打表出来好像也是这样),最后输出dp[m]的方案数就行了。下面是我打的dp过程时的表(数据是样例中的数据)

    • DFS:暴力似乎能解决一切问题(在时间够的情况下)。直接枚举所有的情况,加上剪枝就可以了(这个题加上剪枝并没有减少什么时间,难道是剪枝的姿势不对?)

    AC代码

    DP:

    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <math.h>
    #include <limits.h>
    #include <map>
    #include <stack>
    #include <queue>
    #include <vector>
    #include <set>
    #include <string>
    #define ll long long
    #define ms(a) memset(a,0,sizeof(a))
    #define pi acos(-1.0)
    #define INF 0x3f3f3f3f
    const double E=exp(1);
    const int maxn=1e3+10;
    using namespace std;
    int a[maxn];
    int dp[maxn];//记录拿到总价值为j的物品的方案数
    int main(int argc, char const *argv[])
    {
    	ios::sync_with_stdio(false);
    	int n,m;
    	cin>>n>>m;
    	for(int i=1;i<=n;i++)
    		cin>>a[i];
    	ms(dp);
    	dp[0]=1;
    	for(int i=1;i<=n;i++)
    	{
    		// cout<<"取到第"<<i<<"个物品时"<<endl;
    		for(int j=m;j>=a[i];j--)
    		{
    			dp[j]+=dp[j-a[i]];
    			// cout<<"i:"<<i<<"	"<<"j:"<<j<<"	"<<"a[i]:"<<a[i]<<"	"<<"dp[j]:"<<dp[j]<<endl;
    		}		
    	}
    	cout<<dp[m]<<endl;
    	return 0;
    }
    

    DFS:

    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <math.h>
    #include <limits.h>
    #include <map>
    #include <stack>
    #include <queue>
    #include <vector>
    #include <set>
    #include <string>
    #define ll long long
    #define ms(a) memset(a,0,sizeof(a))
    #define pi acos(-1.0)
    #define INF 0x3f3f3f3f
    const double E=exp(1);
    const int maxn=1e6+10;
    using namespace std;
    int n,m;
    int ans;
    int a[maxn];
    int vis[maxn];//记录这种菜是否选过
    void dfs(int x,int y)//x表示选到第几个菜,y表示当前菜的总价值
    {
    	if(y>m)
    		return ;
    	if(y==m)
    	{
    		ans++;
    		return ;
    	}
    	// 从当前所选的菜的位置向后遍历
    	for(int i=x+1;i<=n;i++)
    	{
    		// 如果当前菜没有被选
    		if(vis[i]==0)
    		{
    			vis[i]=1;
    			dfs(i,y+a[i]);
    			// 回溯
    			vis[i]=0;
    		}
    	}
    	
    }
    int main(int argc, char const *argv[])
    {
    	ios::sync_with_stdio(false);
    	cin>>n>>m;
    	ms(vis);
    	ms(a);
    	for(int i=1;i<=n;i++)
    		cin>>a[i];
    	ans=0;
    	dfs(0,0);
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    poj 2312 Battle City
    poj 2002 Squares
    poj 3641 Pseudoprime numbers
    poj 3580 SuperMemo
    poj 3281 Dining
    poj 3259 Wormholes
    poj 3080 Blue Jeans
    poj 3070 Fibonacci
    poj 2887 Big String
    poj 2631 Roads in the North
  • 原文地址:https://www.cnblogs.com/Friends-A/p/10324405.html
Copyright © 2011-2022 走看看