ACM/ICPC----动态规划

动态规划

动态规划方法的编程实验
在现实中有一类活动,其过程可以分成若干个互相联系的阶段,在它的每一个阶段都需要作出决策,从而使整个过程达到最好的活动效果。在各个阶段决策依赖于当前状态,也引起状态的转移,而一个决策序列就是在变化的状态中产生出来的,故有“动态”的含义。我们称这种解决多阶段决策问题的方法为动态规划(Dynamic Programming,DP)方法,简称为DP方法。
以上是吴永辉老师对动态规划的阐述,有些抽象,简单的说就是当问题比较复杂,无法一步找到正确答案的情况下,找到动态方程分步动态的解决问题



B-Dollars

New Zealand currency consists of 100,100, 100,50, 20,20, 20,10, and 5notesand5 notes and 5notesand2, $1, 50c, 20c, 10c and 5ccoins. Write a program that will determine, for any given amount, in how many ways that amountmay be made up. Changing the order of listing does not increase the count. Thus 20c may be madeup in 4 ways: 120c, 210c, 10c+25c, and 45c.

Input

Input will consist of a series of real numbers no greater than $300.00 each on a separate line. Eachamount will be valid, that is will be a multiple of 5c. The file will be terminated by a line containingzero (0.00).

Output

Output will consist of a line for each of the amounts in the input, each line consisting of the amountof money (with two decimal places and right justified in a field of width 6), followed by the number ofways in which that amount may be made up, right justified in a field of width 17.
Sample Input

0.20
2.00
0.00
Sample Output

0.20 4
2.00 293

题目整体不难,理解题意后稍微变形就可以转变为01背包问题,这里最大的坑点就是,将读入的浮点数*100后不能之间转换成整型数,需要四舍五入,这个点卡了很久,交了9次才发现这个问题。除此之外,因为要读入多组数据,所以,每次读入数据后都要给dp数组进行初始化.

代码:
#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

typedef long long ll;

const int N = 11;
int p[N] = {10000,5000,2000,1000,500,200,100,50,20,10,5};
ll dp[100005];

int main()
{
    double m;
    while(cin >> m)
    {
        memset(dp,0,sizeof(dp));
        if(m == 0)
            break;
        ll v = m*100.0+0.5; //最大坑点!!!
        dp[0] = 1;
        for(int i = 0 ; i < N ; i++)
        {
            for(int j = p[i] ; j <= v ; j++)
            {
                dp[j] += dp[j - p[i]];
            }
        }
        printf("%6.2f%17lld\n",v*1.0/100,dp[v]);//这里注意按照题目要求的格式输出
    }
    return 0;
}


D – Charm Bracelet

Bessie has gone to the mall’s jewelry store and spies a charm bracelet. Of course, she’d like to fill it with the best charms possible from the N (1 ≤ N ≤ 3,402) available charms. Each charm i in the supplied list has a weight Wi (1 ≤ Wi ≤ 400), a ‘desirability’ factor Di (1 ≤ Di ≤ 100), and can be used at most once. Bessie can only support a charm bracelet whose weight is no more than M (1 ≤ M ≤ 12,880).Given that weight limit as a constraint and a list of the charms with their weights and desirability rating, deduce the maximum possible sum of ratings.

Input

*Line 1: Two space-separated integers: N and M
*Lines 2…N+1: Line i+1 describes charm i with two space-separated integers: Wi and Di

Output

Line 1: A single integer that is the greatest sum of charm desirabilities that can be achieved given the weight constraints

Sample Input

4 6
1 4
2 6
3 12
2 7

Sample Output

23

这是一道简单的背包模板题:

代码:
#include <iostream>
 
using namespace std;
 
const int maxm = 40005;
int w[maxm],c[maxm];
int dp[maxm];
 
int main()
{
    int n,m;
    cin >> n >> m;
    for(int i = 0 ; i < n ; i++)
        cin >> w[i] >> c[i];
    for(int i = 0 ; i < n ; i++)
    {
        for(int j = m ; j >= w[i] ; j--)
            dp[j] = max(dp[j],dp[j-w[i]] + c[i]);
    }
    cout << dp[m];
    return 0;
}


E – Dollar Dayz

Farmer John goes to Dollar Days at The Cow Store and discovers an unlimited number of tools on sale. During his first visit, the tools are selling variously for 1,1, 1,2, and 3.FarmerJohnhasexactly3. Farmer John has exactly 3.FarmerJohnhasexactly5 to spend. He can buy 5 tools at 1eachor1toolat1 each or 1 tool at 1eachor1toolat3 and an additional 1 tool at 2.Ofcourse,thereareothercombinationsforatotalof5differentwaysFJcanspendallhismoneyontools.Heretheyare:1@US2. Of course, there are other combinations for a total of 5 different ways FJ can spend all his money on tools. Here they are: 1 @ US2.Ofcourse,thereareothercombinationsforatotalof5differentwaysFJcanspendallhismoneyontools.Heretheyare:1@US3 + 1 @ US21@US2 1 @ US21@US3 + 2 @ US11@US1 1 @ US11@US2 + 3 @ US12@US1 2 @ US12@US2 + 1 @ US15@US1 5 @ US15@US1
Write a program than will compute the number of ways FJ can spend N dollars (1 <= N <= 1000) at The Cow Store for tools on sale with a cost of 1…1…1…K (1 <= K <= 100)

Input

A single line with two space-separated integers: N and K.

Output

A single line with a single integer that is the number of unique ways FJ can spend his money.

Sample Input

5 3

Sample Output

5

1 @ US3+1@US3 + 1 @ US3+1@US2

1 @ US3+2@US3 + 2 @ US3+2@US1

1 @ US2+3@US2 + 3 @ US2+3@US1

2 @ US2+1@US2 + 1 @ US2+1@US1

5 @ US1WriteaprogramthanwillcomputethenumberofwaysFJcanspendNdollars(1<=N<=1000)atTheCowStorefortoolsonsalewithacostof1 Write a program than will compute the number of ways FJ can spend N dollars (1 <= N <= 1000) at The Cow Store for tools on sale with a cost of 1WriteaprogramthanwillcomputethenumberofwaysFJcanspendNdollars(1<=N<=1000)atTheCowStorefortoolsonsalewithacostof1…$K (1 <= K <= 100).

Input

A single line with two space-separated integers: N and K.

Output

A single line with a single integer that is the number of unique ways FJ can spend his money.

Sample Input

5 3

Sample Output

5

这题的主要难度在于,数据范围超过了long long 如果用Java里的大整数可以直接提交通过,但在C++里只能通过取模的方式,将高位和低为分别存储,最后看高位是否为0,如果为0就只输出低位,否则就输出高位和低位。

代码:
#include <iostream>
#include <cmath>
 
using namespace std;
const int maxm = 100005;
typedef long long ll;
ll dp1[maxm],dp2[maxm];
ll w[maxm];
ll m = 1e18;
 
int main()
{
    int N,K;
    cin >> N >> K;
    dp1[0] = 1;
    for(int i = 1 ; i <= K ; i++)
    {
        for(int v = i ; v <= N ; v++)
        {
            dp2[v] = dp2[v] + dp2[v - i] + (dp1[v] + dp1[v - i]) / m;
            dp1[v] = (dp1[v] + dp1[v - i]) % m;
        }
    }
    if(dp2[N] != 0)
        cout << dp2[N];
    cout << dp1[N];
    return 0;
}


F – Piggy-Bank

Before ACM can do anything, a budget must be prepared and the necessary financial support obtained. The main income for this action comes from Irreversibly Bound Money (IBM). The idea behind is simple. Whenever some ACM member has any small money, he takes all the coins and throws them into a piggy-bank. You know that this process is irreversible, the coins cannot be removed without breaking the pig. After a sufficiently long time, there should be enough cash in the piggy-bank to pay everything that needs to be paid.

But there is a big problem with piggy-banks. It is not possible to determine how much money is inside. So we might break the pig into pieces only to find out that there is not enough money. Clearly, we want to avoid this unpleasant situation. The only possibility is to weigh the piggy-bank and try to guess how many coins are inside. Assume that we are able to determine the weight of the pig exactly and that we know the weights of all coins of a given currency. Then there is some minimum amount of money in the piggy-bank that we can guarantee. Your task is to find out this worst case and determine the minimum amount of cash inside the piggy-bank. We need your help. No more prematurely broken pigs!

Input

The input consists of T test cases. The number of them (T) is given on the first line of the input. Each test case begins with a line containing two integers E and F. They indicate the weight of an empty pig and of the pig filled with coins. Both weights are given in grams. No pig will weigh more than 10 kg, that means 1 <= E <= F <= 10000. On the second line of each test case, there is an integer number N (1 <= N <= 500) that gives the number of various coins used in the given currency. Following this are exactly N lines, each specifying one coin type. These lines contain two integers each, Pand W (1 <= P <= 50000, 1 <= W <=10000). P is the value of the coin in monetary units, W is it’s weight in grams.

Output

Print exactly one line of output for each test case. The line must contain the sentence “The minimum amount of money in the piggy-bank is X.” where X is the minimum amount of money that can be achieved using coins with the given total weight. If the weight cannot be reached exactly, print a line “This is impossible.”.

Sample Input

3
10 110
2
1 1
30 50
10 110
2
1 1
50 30
1 6
2
10 3
20 4

Sample Output

The minimum amount of money in the piggy-bank is 60.
The minimum amount of money in the piggy-bank is 100.
This is impossible.

这题中规中矩,背包问题,在寻找最小值方面,要对dp初始化为无穷大,dp[0] = 0,由于需要输入多组数据,所以每次都要初始化,在判断是否存在这样的重量时只需要判断dp[f-e]是否为无穷大即可,如果时无穷大就输出Impossible。

代码:
#include <iostream>

using namespace std;

const int maxm = 100005;
const int inf = 1e7;
int w[maxm],p[maxm];
int dp[maxm];

int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        fill(dp,dp+maxm,inf);
        int e,f,n;
        cin >> e >> f >> n;
        dp[0] = 0;
        for(int i = 0 ; i < n ; i++)
            cin >> p[i] >> w[i];
        for(int i = 0 ; i < n ; i++)
        {
            for(int j = w[i] ; j <= f - e; j++)
            {
                dp[j] = min(dp[j],dp[j - w[i]] + p[i]);
            }
        }
        if(dp[f-e] == inf)
            cout << "This is impossible." << endl;
        else
            cout << "The minimum amount of money in the piggy-bank is " << dp[f-e] <<"." << endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柠檬ya

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值