牛客网-美丽的项链

题目:

妞妞参加了Nowcoder Girl女生编程挑战赛, 但是很遗憾, 她没能得到她最喜欢的黑天鹅水晶项链。

于是妞妞决定自己来制作一条美丽的项链。一条美丽的项链需要满足以下条件:

1、需要使用n种特定的水晶宝珠

2、第i种水晶宝珠的数量不能少于li颗, 也不能多于ri

3、一条美丽的项链由m颗宝珠组成

妞妞意识到满足条件的项链种数可能会很多, 所以希望你来帮助她计算一共有多少种制作美丽的项链的方案。

题目分析:

我的想法是递归(刚刚有点递归的感觉,想起来也就是树形结构往后遍历,但是递归的资源占用超出要求内存了);看到有人用动态规划算法写的,我觉得很厉害,虽然想用动态规划,但是没想到状态转移公式,但是别人就能想到,我慢慢修炼学习吧,刷的题目太少了,以下是动态规划的代码(我觉得这个思路简直绝了):

链接:https://www.nowcoder.com/questionTerminal/e7e0230b12de4239a7f547a01d731522
来源:牛客网

#include<stdio.h>
#include<string.h>
const int maxn=100;
#define max(a,b) a>b?a:b
int n,m,a[maxn],l[maxn],r[maxn];
long long dp[maxn][maxn+1];
int main(){
    int i,j,k;
    //freopen("input.txt","r",stdin);
    while(~scanf("%d%d",&n,&m)){
        for(i=0;i<n;i++) scanf("%d%d",l+i,r+i);
        memset(dp,0,sizeof(dp));//将动态数组全部置0
        for(i=l[0];i<=r[0];i++) dp[0][i]=1;//当只用一种宝珠的时候,因为第一种只能用l[0]~r[0]颗,对应的是l[0]~r[0]颗宝珠的项链,前一种宝珠的方案都是1种。
        for(i=1;i<n;i++)
            for(j=1;j<=m;j++){
                int left=max(0,j-r[i]),right=max(0,j-l[i]);//这两个区间对应的是当前 前i种宝珠取多少个,最少取(j-r[i]),最多取(j-l[i]);
                for(k=left;k<=right;k++) dp[i][j]+=dp[i-1][k];那么这个区间就对应的前i-1宝珠在(j-l[i]~j-r[i])区间所有方案,其总和就对应的j个宝珠的项链用前i种宝珠的方案总数
            }
        printf("%lld\n",dp[n-1][m]);
    }
}//dp[i][j]表示用前i种宝石组成j颗宝石的项链的方案数
 //但是第i种只能是l[i]到r[i]之间的数量
 //所以dp[i][j]=dp[i-1][j-r[i]]+dp[i-1][j-r[i]+1]+...+dp[i-1][j-l[i]]

下面是我递归写的,有70%通过了,但是超出要求内存限制了。我的思路是从LeetCode上面的一个寻找一颗二叉树上的一段路径上元素之和等于target这个题目来的。

扫描二维码关注公众号,回复: 1062263 查看本文章
#include <iostream>
#include <stdlib.h>
#include <vector>
using namespace std;
int sum = 0;
int n;
void sumKind(int perls, int gap, vector<int> l,vector<int> r)
{
	if (gap < 0) return;//
	if (perls == n - 1 &&gap > r[perls]) return;
	if (perls == n - 1 &&gap >= l[perls]&&gap <= r[perls]) { sum++; return; }//就是每找到一条方案路径就sum++
	for (int i=l[perls];i<=r[perls];i++)
	{
		sumKind(perls + 1, gap - i, l, r);//第perls 种就再往后找第perls+1种对应的方案,直到这条路走不通,然后返回来,继续走下一个方案
	}
}
int main()
{
	int m;
	cin >> n>>m;
	vector<int> l(n, -1), r(n, -1);
	for (int i = 0;i<n;i++)
	{
		cin >> l[i] >> r[i];
	}
	sumKind(0, m, l, r);
	cout << sum << endl;
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_18548149/article/details/79592746