Codeforces Round #436 (Div. 2)E,F详解

来源:互联网 发布:多益网络客服电话 编辑:程序博客网 时间:2024/06/05 02:28

鉴于太多人把D做出来了,实际上D就是道模拟简单题,所以本篇博客并没有D的题解。如果有需要的读者可以联系博主,博主会很热心的为你解释的(笑)。。
E题题解:Polycarp家着火了。。他家里有n个值钱的东西,每一个东西有一个营救需要的时间和一个烧毁需要的时间。问Polycarp能救出的东西的最大价值为多少,并输出营救顺序。
思路:裸的01背包问题。。如果不明白01背包问题可以看看紫书的动规专题。
思路出来了,博主觉得有必要讲的两点就是,一,它和01背包问题唯一不同的是有一个限制时间,不像01背包啥时候都可以拿,它拿某个物品的时间是一段区间。二,能拿某个物品的时间怎么算,首先状态转移方程式为
dp[T]=max(dp[T],dp[T-t[i]]+w[i]),显然T< d[i],并且T>t[i].所以只会更新该区间的值,但更新完了肯定会影响后面的T(从这个式子就可以看出),所以为了复杂度低(你也可以更新后面的T,加个判断即可),首先把物品按照d排个序,先取小的,再取大的,这样就可保证再更新大的时候小的已经全部被更新了。
代码如下:

#include<iostream>#include<vector>#include<algorithm>using namespace std;struct node{    int t, d, p;    int idx;    bool operator<(const node &b)const    {        return d < b.d;    }}nodes[205];vector<int>V[2005];int dp[2005];int main(){    int n;    cin >> n;    for (int i = 1;i <= n;i++)    {        scanf("%d%d%d", &nodes[i].t, &nodes[i].d, &nodes[i].p);        nodes[i].idx = i;    }    sort(nodes + 1, nodes + 1 + n);    for(int i=1;i<=n;i++)        for (int j = nodes[i].d - 1;j >= nodes[i].t;j--)        {            if (dp[j] < dp[j - nodes[i].t] + nodes[i].p)            {                dp[j] = dp[j - nodes[i].t] + nodes[i].p;                V[j] = V[j - nodes[i].t];                V[j].push_back(nodes[i].idx);            }        }    int theans = 0;    int idx=-1;    for(int i=0;i<=2000;i++)        if (theans < dp[i])        {            theans = dp[i];            idx = i;        }    cout << theans << endl;    if (idx == -1)    {        cout << 0 << endl;        return 0;    }    int Size = V[idx].size();    cout << Size << endl;    for (int i = 0;i < Size;i++)    {        if (i != 0)printf(" ");        printf("%d", V[idx][i]);    }    return 0;}

F题题意:给你一个图,有q次询问,从s到t的结点最小字典序路径中的第k个结点是谁。
思路:这题好啊,让博主学习到了图上的倍增。另外也让博主领悟到了一个小套路,即如果题目给你一个k,让你求路径上的第k个点,这大概就需要用倍增的思想了。
思路挺简单的,那么如何用倍增呢?请读者仔细看代码,并理解从中倍增的奥妙和如何用倍增判断是环的。

#include<iostream>#include<vector>#include<algorithm>#include<cstring>using namespace std;const int maxn = 3005;const int maxq = 4e5 + 10;vector<int>G[maxn], TO[maxn];vector < pair<pair<int, int>, int>>Q[maxq];bool vis[maxn];#define MP(x,y) make_pair(x,y)void dfs(int node){    if (vis[node])return;    vis[node] = 1;    for (int i : TO[node])        dfs(i);}int st[maxn][13];int ans[maxq];int main(){    int n, m, q;    cin >> n >> m >> q;    int u, v;    for (int i = 1;i <= m;i++)    {        scanf("%d%d", &u, &v);        G[u].push_back(v);        TO[v].push_back(u);    }    int s, t, k;    for (int i = 1;i <= q;i++)    {        scanf("%d%d%d", &s, &t, &k);        Q[t].push_back(MP(MP(s, k), i));    }    for (int i = 1;i <= n;i++)sort(G[i].begin(), G[i].end());    for (int i = 1;i <= n;i++)if(Q[i].size())    {        memset(vis, 0, sizeof(vis));        dfs(i);        memset(st, 0, sizeof(st));        for (int j = 0;j < 13;j++)st[n + 1][j] = n + 1;        for (int j = 1;j <= n;j++)        {            if (j == i)st[j][0] = n + 1;            else if (vis[j])            {                for (int v : G[j])                {                    if (!vis[v])continue;                    st[j][0] = v;                    break;                }            }        }        for (int j = 1;j < 13;j++)            for (int u = 1;u <= n;u++)if(vis[u])                st[u][j] = st[st[u][j - 1]][j - 1];        for (auto it : Q[i])        {            int s = it.first.first;            int k = it.first.second - 1;            int id = it.second;            if (vis[s])            {                if (st[s][12] == n + 1)                {                    for (int j = 0;j < 13;j++)                        if (k&(1 << j))                            s = st[s][j];                    if (s != n + 1)                        ans[id] = s;                    else                        ans[id] = -1;                }                else                    ans[id] = -1;            }            else            {                ans[id] = -1;            }        }    }    for (int i = 1;i <= q;i++)        cout << ans[i] << endl;    return 0;}

代码浑然天成啊。。。博主想解释为啥用离线,但感觉没必要,因为都这样写了,还能用在线不成。希望读者仔细阅读代码,学会了又有新姿势上分了~

原创粉丝点击