PAT 顶级(记忆化搜索)——1002 Business (35 分)

1002 Business (35 分)


解题思路:

N<=50,P,L,D未知,暴力搜索2^50会T一个点,尝试记忆化搜索(数据范围未知所以不确定),用vis记录<i,now,ans>i为当前dfs的位置,now为当前的时间,ans为当前的答案,用if (vis[i][now][ans])return;来实现记忆化搜索,减少搜索复杂度。

坑点:

若破坏某个城市后网络不连通,则该城市的代价为最大(如果有多个这样的城市,则输出多个)

代码:

#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define mp make_pair
#define pb push_back
#define G 6.67430*1e-11
#define  rd read()
#define pi 3.1415926535
using namespace std;
const ll mod = 998244353;
const int MAX1 = 100005;
const int MAX2 = 300005;
inline ll read() {
    ll x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch>'9') {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}
ll gcd(ll a, ll b) { return !b ? a : gcd(b, a % b); }
struct ss
{
    int num, time, ddl, flag;
}x[55];
int n;
int a = 0;
map<int,map<int,map<int,int>>> vis;
void dfs(int i, int now, int ans)
{
    if (i >= n)
    {
        //cout << ans << endl;
        a = max(a, ans);
        return;
    }
    if (vis[i][now][ans])return;
    vis[i][now][ans] = 1;
    if (now + x[i].time > x[i].ddl || !x[i].flag)return dfs(i + 1, now, ans);
    else
    {
        dfs(i + 1, now + x[i].time, ans + x[i].num);
        dfs(i + 1, now, ans);
    }
}
bool cmp(ss a, ss b)
{
    return a.ddl < b.ddl||(a.ddl==b.ddl&&a.time<b.time);
}
signed main()
{
    n = rd;
    for (int i = 0; i < n; i++)
    {
        x[i].num = rd;
        x[i].time = rd;
        x[i].ddl = rd;
        x[i].flag = 1;
    }
    sort(x, x + n, cmp);
    for (int i = 1; i < n; i++)
    {
        if (x[i].ddl == x[i - 1].ddl && x[i].time == x[i - 1].time)
        {
            int ma = x[i - 1].num;
            int j = i;
            while (x[i].ddl == x[i - 1].ddl && x[i].time == x[i - 1].time)
            {
                x[i].flag = 0;
                
                ma = max(x[i].num, ma);
                i++;
            }
            x[j - 1].num = ma;
        }

    }
    //for (int i = 0; i < n; i++)
    //{
    //    cout << x[i].num << ' ' << x[i].time << ' ' << x[i].ddl << ' ' << x[i].flag << endl;
    //}
    dfs(0, 0, 0);
    cout << a;
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值