玩命加载中 . . .

The County Fair


题目分析

首先需要明确的是,我们要尽可能地按照礼品发放时间先后顺序考虑来拿取礼品,这样才会拿到数量更多的礼品。
这里提供一种动态规划的思路做法。我们需要用数组存储每一个集市以及它发放礼品的时间。在按照时间从小到大顺序排序(sort)之后,考虑第i个礼品拿到的情况下,前i个礼品中拿到礼品的数量,记作dp[i]。此时,需要遍历i号元素之前的所有元素。一旦时间上可以满足“从j号集市赶到i号集市,拿到i号集市的礼品”,就考虑是否更新dp[i](考虑原来的dp[i]和dp[j]+1哪个更大)。不满足dp[i]保持不变。状态转移方程即为:

dp[i] = max(dp[i], dp[j]+1) // j小于i,

关键代码实现

typedef pair<int, int> P;	// <集市号,分发时间>

int mapt[405][405];	// t_i,j
P mak[405];

for (int i = 1; i <= n; i++)
{
    for (int j = 0; j < i; j++)
    {
        // 表示可以赶上第i个礼品发放时间
        if (mapt[mak[j].first][mak[i].first] + mak[j].second <= mak[i].second)
        {
            dp[i] = (dp[j] + 1) > dp[i] ? (dp[j] + 1) : dp[i];
        }
        // 如果赶不上,默认dp[i]保持不变,不作处理
    }
}

完整代码

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;

int mapt[405][405];
P mak[405];
int dp[405];
int n;
int ans;

bool com(P a, P b)
{
    return a.second < b.second;
}

int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        int t;
        cin >> t;
        mak[i] = { i,t };
    }
    mak[0] = { 1,0 };   // 记录初始情况,t=0,从1号集市开始
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            cin >> mapt[i][j];
        }
    }
    sort(mak + 1, mak + 1 + n, com);
   
    for (int i = 1; i <= n; i++)
    {
        for (int j = 0; j < i; j++)
        {
            //表示可以赶上第i个礼品发放时间
            if (mapt[mak[j].first][mak[i].first] + mak[j].second <= mak[i].second)
            {
                dp[i] = (dp[j] + 1) > dp[i] ? (dp[j] + 1) : dp[i];
            }
        }
    }
    
    // 注意,需要综合考虑所有的dp,取其中的最大值,因为之前的“dp[i]表示第i个礼品一定取到”只是一个假设,但是总会取到一个礼品,使得最后的礼品数量最多
    sort(dp + 1, dp + 1 + n);
    cout << dp[n] << endl;
}

文章作者: 鹿卿
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 鹿卿 !
评论
  目录