美酒问题 + 木桶倒水问题(当当网编程题)

  • 1. 题目描述
    小李有n(1<=n<=2000)瓶美酒,他想卖掉它们来赚钱。这些美酒放在一些,它们有些有趣的特性:
    (1)这些美酒被编号1~n,每一天小李可以从这排箱子的头部或者尾部去除美酒去卖;
    (2)这些美酒放得越久,年龄越大,价值越大,美酒i有一个初始的价值V(i);
    (3)放了a天后,年龄为a,美酒最终的价值为V[i]*a。
    给定每一瓶美酒的初始价值V[i],请求出小李卖掉它们后可以获得的最大价值,第一天出售的美酒的年龄为1,此后每增加一天美酒的年龄就增加1.

提示
样例说明:小李出售这些美酒(初始价值1,3,1,5,2)的顺序为:第一天卖掉第1瓶,第二天卖掉第5瓶,第三天卖掉第2瓶,第四条卖掉第3瓶,第5天卖掉第4瓶,获得最大的价值为:
1*1+2*2+3*3+4*1+5*5=43

输入示例:
5
1
3
1
5
2
输出示例
43

/*************************************************
* 思路:由于只能去头部和尾部的美酒,因此使用头尾指针法,
* 每次选择头部和尾部中价值最小的美酒,然后乘以当前的天数得
* 到当前该美酒的价值。将所有卖掉的钱相加即可。
* ***********************************************/
#include <iostream>
using namespace std;

int main()
{
    int n;
    cin >> n;
    int* V = new int[n];
    int i, j;
    for (i = 0; i< n;i++)
        cin >> V[i];
    if (n == 1)    // 如果只有一瓶美酒,直接输出
    {
        cout << V[0] << endl;
        return 0;
    }
    int max_value = 0;   // 初始化卖出的美酒的最大值
    int days = 1;
    for (i = 0, j = n-1; i!= j; )   
    {
        if (V[i] < V[j])   // 若剩余的美酒第一瓶美酒的价格比第二瓶美酒的价格小
        {
            max_value += V[i]*days;
            i++;
        }
        else{
            max_value+=V[j]*days;
            j--;
        }
        days++;
    }
    max_value += V[i]*days;  // 加上剩下的最后一瓶美酒
    cout << max_value << endl;   // 输出打印
    return 0;
}
  • 2. 题目描述
    要把m升的水倒入n个相同的木桶中(假设木桶足够大),允许有的木桶是空的,问共有多少种不同的倒法?(用k表示)5,1,1和1,5,1和1,1,5是同一种做法。
    输入
    第一行是测试数据的数目x(表示有多少组输入,0<=x<=20)。以下每行均包含2个整数m和n,以空格分开。1<=m, n<=10。
    输出
    对输入的每行数据m和n,用一行输出相应的k。

输入示例:
1
7 3
输出示例:
8

#include <iostream>
using namespace std;

int count = 0;
void func(int first, int second, int third, int forth, int fifth)
{
    if (third > forth) 
      return ;
    for (int i = fifth; i >= 0; i--)
    {
      if (first == second && (third + i) == forth)
        count++;
      else if (first < second)
        func(first+1, second, third+i, forth, i);
    }
}

void usefunc(int x, int y)
{
    count = 0;
    func(0, y-1, 0, x, x);
    cout << count << " ";  // 用一行输出相应的k
}

int main()
{
  int x;
  cin >> x;
  int* m = new int[x];
  int* n = new int[x];
  for (int i = 0; i < x; i++)
    cin >> m[i] >> n[i];
  for (int i = 0; i < x; i++)
    usefunc(m[i], n[i]);
  return 0;
}

DP算法,上面代码参考博客(我还没怎么看):
http://blog.csdn.net/wsyxhwj/article/details/51591173

#include <iostream>
using namespace std;

int func(int m, int n)
{
    int sum = 0;
    // 下面是边界条件
    // 当有0升水时,有0种倒法
    if (m == 0)
        return 0;
    // 当有1升水或只有1个容器时,有1种倒法
    if (m == 1 || n == 1)
        return 1;
    // 若水的容积数m小于桶数n,则最多只需要m个桶
    if (m < n)
        n = m;
    // 迭代递归实现
    for (int i = 1; i <= n; i++)
    {
        if (i == 1)
            sum += func(m, i);
        else
            sum += func(m-i, i);
    }
    return sum;
}

int main()
{
    int m, n;
    cin >> m >> n;
    cout << "共有" << func(m, n) << "种倒法。" << endl;
    return 0;
}

参考博客: http://blog.csdn.net/coder_ken/article/details/51023980

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值