Kattis - bank 【简单DP】

Kattis - bank 【简单DP】

Description
Oliver is a manager of a bank near KTH and wants to close soon. There are many people standing in the queue wanting to put cash into their accounts after they heard that the bank increased the interest rates by 42% (from 0.01% per year to 0.0142% per year).

However, there are too many people and only one counter is open which can serve one person per minute. Greedy as Oliver is, he would like to select some people in the queue, so that the total amount of cash stored by these people is as big as possible and that money then can work for the bank overnight.

There is a problem, though. Some people don’t have the time to wait until the bank closes because they have to run somewhere else, so they have to be served before a certain time, after which they just leave. Oliver also turned off the infrared door sensor outside the bank, so that no more people can enter, because it’s already too crowded in the hall.
Task

Help Oliver calculate how much cash he can get from the people currently standing in the queue before the bank closes by serving at most one person per minute.

Input

The first line of input contains two integers N
(1≤N≤10000) and T (1≤T≤47), the number of people in the queue and the time in minutes until Oliver closes the bank. Then follow N lines, each with 2 integers ci and ti, denoting the amount of cash in Swedish crowns person i has and the time in minutes from now after which person i leaves if not served. Note that it takes one minute to serve a person and you must begin serving a person at time ti at the latest. You can assume that 1≤ci≤100000 and 0 ≤ ti < T

Output

Output one line with the maximum amount of money you can get from the people in the queue before the bank closes.
Sample Input 1

4 4
1000 1
2000 2
500 2
1200 0

Sample Output 1

4200

Sample Input 2

3 4
1000 0
2000 1
500 1

Sample Output 2

3000

题意

大概就是有很多人去银行排队存钱,银行当然希望存的钱越多越好。但是每个客户的忍耐是有限度的。银行每分钟处理一个客户后每个客户有一个最大的等待时间,就是到了这个时间,银行还不存他的钱,他就走了。求银行最大能得到多少存款。

思路一
这个是先将数据按照等待时间的大小 从小到大排序,然后用01背包的模型,但是在状态转移之前 判断一下 目前的时间 是不是小于等于客户的最大等待时间,如果是,就可以进行转移。但是,最后转移的状态不是dp[t], 所以 在规划过程中找一下最大值,输出最大值就可以了。

代码一

#include<iostream>       
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
const int MAX = 0x3f3f3f3f;
const int MIN = 0xc0c0c0c0;
const int maxn = 1e4 + 5;
struct node
{
    int v, t, pre;
}q[maxn];
int dp[50];
int comp(node x, node y)
{
    if (x.t == y.t) return x.v > y.v;
    return x.t < y.t;
}
int main()
{
    int n, t;
    cin >> n >> t;
    int i, j, k;
    for (i = 0; i < n; i++)
        scanf("%d%d", &q[i].v, &q[i].t);
    sort(q, q+n, comp);
    memset(dp, 0, sizeof(dp));
    int MAXN = MIN;
    for (i = 0; i < n; i++)
    {
        for (j = t; j >= 1; j--)
        {
            if (j - 1 <= q[i].t)
            {
                dp[j] = max(dp[j], dp[j - 1] + q[i].v);  
            }
            if (dp[j] > MAXN)              //找出规划过程中的最大值
                MAXN = dp[j];
        }
    }
    cout << MAXN << endl;
}

思路二

我们可以先按客户存钱的多少 从大到小排序 然后定义一个数组 比如 dp[t],用来存放当前时间点的客户存钱数 刚开始初始化为0; 对客户的人数 从 0 -> N FOR 一遍 FOR 的时候 每次判断一下 dp[t [i] ] 是否 == 0 如果 == 0 的话 就直接 赋值就可以了 如果 != 0 那就要往前找 因为 我们首先是按照钱的多少来排序的,如果在DP数组往前找 找不到一个位置 == 0(或者理解为前面的都已经安排好了) 那么这个客户 如果处理了 就不是最优解了,因为 在它前面被安排下的 都是钱数比它大的 而它自己的最大忍耐时间却到了,又不能往后走,往前走又没有位置,所以最后 对dp[0] - dp[t] 求和一下 就是最优解

代码二

#include<iostream>          
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<numeric>
using namespace std;
const int MAX = 0x3f3f3f3f;
const int MIN = 0xc0c0c0c0;
const int maxn = 1e4 + 5;
struct node
{
    int v, t;
}q[maxn];
int dp[50];
int comp(node x, node y)
{
    if (x.v == y.v)
        return x.t < y.t;
    return x.v > y.v;
}
int main()
{
    int n, t;
    cin >> n >> t;
    memset(dp, 0, sizeof(dp));
    int i, j;
    for (i = 0; i < n; i++)
        scanf("%d%d", &q[i].v, &q[i].t);
    sort(q, q+n, comp);
    int tot = 0;
    for (i = 0; i < n; i++)
    {
        for (j = q[i].t; j >= 0; j--)
        {
            if (dp[j] == 0)
            {
                dp[j] = q[i].v;
                tot += dp[j];
                break;
            }
        }
    }
    cout << tot << endl;
}
posted @ 2018-02-28 23:06  Dup4  阅读(170)  评论(0编辑  收藏  举报