[NOI2020]美食家 题解
题意分析
给出一个带权有向图,要求从节点 $1$ 出发,经过恰好 $T$ 的边权和,回到节点 $1$ ,求可经过的最大点权和。特别地,经过的边权和达到部分特殊数时,会有某个点的点权发生改变。
思路分析
朴素算法
- 时间复杂度: $O(mT)$
- 理论得分: $40pts$
设 $f_{i,j}$ 表示在节点 $j$ ,经过的边权和为 $i$ 时可经过的最大点权和。很容易可以得出 DP 方程:
$$f_{i,j}=\max_{(x,j)\in E}(f_{i-val(x,j),x})+c_j$$
暴力转移,点权改变的情况特判修改即可。
优化1
- 时间复杂度: $O(125n^3k\log T)$
- 理论得分:$75pts$
可以发现 $w$ 的数据范围很小,想到用矩阵快速幂优化。
首先拆点,令所有边边权都为 $1$ ,然后将所求的点权转化为边权:设有 $(u,v,w)\in E$ ,则可以将 $u$ 拆成 $u_0,u_1,...,u_{w-1}$ ,从 $u_{i-1}$ 向 $u_i$ 间连一条边,边权为 $0$ ,然后从 $u_{w-1}$ 向 $v$ 连一条边,边权为 $c_v$ 。
这样,问题就转化为,从节点 $1$ 出发,经过 $T$ 条边,回到节点 $1$ ,求可经过的最大边权和,即最长路。
定义一个广义矩阵乘法 $ans_{i,j}=max(a_{i,k}+b_{k,j})$ 。可以证明这个广义矩阵乘法同样满足矩阵乘法的基本运算律,如结合律。
设邻接矩阵为 $a$ ,可以很容易得出 DP 方程:
$$dp_i=dp_j*a^{i-j}$$
点权改变的情况怎么处理?只要先将时间从小到大排序,然后在相邻的时间之间转移,转移后在改变点权在邻接矩阵中的对应位置修改即可。
优化2
- 时间复杂度: $O(125n^3\log T+25n^2k\log T)$
- 理论得分: $100pts$
分析过后可以发现,因为要求的只是 $dp_{T_{1,1}}$ ,因此只要保留 $dp$ 矩阵的第一行即可;另外,发现在转移的时候要多次乘上邻接矩阵 $a$ 的相同次幂,因此可以先预处理出 $a$ 的 $2$ 的整数次幂。这样处理之后可以降低一维的复杂度。
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- #define ll long long
- using namespace std;
- const int N=300;
- const ll INF=0xcfcfcfcfcfcfcfcf;
- struct Node
- {
- ll p[N][N];
- }a[31];
- struct Fes
- {
- int t,x,y;
- #define t(i) b[i].t
- #define x(i) b[i].x
- #define y(i) b[i].y
- }b[N];
- int n,m,T,K;
- int c[N],id[N][5];
- ll dp[N];
- Node Max(Node x)
- {
- Node now;
- for(int i=1;i<=n;i++)
- for(int j=1;j<=n;j++)
- {
- now.p[i][j]=INF;
- for(int k=1;k<=n;k++)
- now.p[i][j]=max(now.p[i][j],x.p[i][k]+x.p[k][j]);
- }
- return now;
- }//广义矩阵乘法
- void Maxx(Node x)
- {
- ll now[N];
- for(int i=1;i<=n;i++)
- {
- now[i]=INF;
- for(int j=1;j<=n;j++)
- now[i]=max(now[i],dp[j]+x.p[j][i]);
- }
- for(int i=1;i<=n;i++)
- dp[i]=now[i];
- }//一维乘二维
- void pre()
- {
- for(int i=1;i<=30;i++)
- a[i]=Max(a[i-1]);
- }//预处理次幂
- void fastpow(int x)
- {
- for(int i=30;i>=0;i--)
- if(x&(1<<i))
- Maxx(a[i]);
- }//快速幂
- bool cmp(Fes x,Fes y)
- {
- return x.t<y.t;
- }
- int main()
- {
- scanf("%d%d%d%d",&n,&m,&T,&K);
- for(int i=1;i<=n;i++)
- scanf("%d",&c[i]),id[i][0]=i;
- memset(a,0xcfcf,sizeof(a));
- for(int i=1,u,v,w;i<=m;i++)
- {
- scanf("%d%d%d",&u,&v,&w);
- for(int j=1;j<w;j++)
- {
- if(!id[u][j])
- id[u][j]=++n;
- a[0].p[id[u][j-1]][id[u][j]]=0;
- }
- a[0].p[id[u][w-1]][v]=c[v];//拆点
- }
- pre();
- for(int i=1;i<=K;i++)
- scanf("%d%d%d",&t(i),&x(i),&y(i));
- sort(b+1,b+K+1,cmp);t(K+1)=T;
- memset(dp,0xcfcf,sizeof(dp));dp[1]=c[1];//初状态
- for(int i=1,d;i<=K+1;i++)
- {
- d=t(i)-t(i-1);
- fastpow(d);
- dp[x(i)]+=y(i);//点权改变
- }//在相邻的时间之间转移
- printf(dp[1]<0?"-1":"%lld",dp[1]);
- return 0;
- }
[NOI2020]美食家 题解的更多相关文章
- P6772 [NOI2020]美食家
题目大意 给你一个 \(n\) 个点,\(m\) 条边的有向图,每条边有一个权值 \(w_i\) ,每个节点有一个权值 \(a_i\) . 你从节点 \(1\) 出发,每经过一个节点就可以获得该点的权 ...
- [XIN算法应用]NOI2020美食家
XIN(\(updated 2021.6.4\)) 对于很多很多的题目,发现自己并不会之后,往往会直接冲上一个XIN队算法,然而,这样 \(\huge{\text{鲁莽}}\) 的行为只能获得 TLE ...
- [NOI2020] 美食家
很好,自己会做NOI签到题了,去年只要会这题,再多打点暴力,\(Ag\)到手,希望今年\(NOI\)同步赛过\(Ag\)线吧,得有点拿得出手的成绩证明啊. 考虑\(T\)非常大,\(n\)又很小. 想 ...
- 洛谷 P6772 - [NOI2020]美食家(广义矩阵快速幂)
题面传送门 题意: 有一张 \(n\) 个点 \(m\) 条边的有向图,第 \(0\) 天的时候你在 \(1\) 号城市,第 \(T\) 天的时候你要回到 \(1\) 号城市. 每条边上的边权表示从城 ...
- 【NOI2020】美食家(矩阵)
Description 给定一张有向图,\(n\) 个顶点,\(m\) 条边.第 \(i\) 条边从 \(u_i\) 到 \(v_i\),走完该边的用时为 \(w_i\).每一个点有一个价值 \(c\ ...
- XIN队算法
XIN队算法 注:名称由莫队算法改编而来 从luogu搬过来了... \(newly\;upd:2021.7.8\) \(newly\;upd:2021.6.6\) OI至高算法,只要XIN队算法打满 ...
- [BZOJ1691][Usaco2007 Dec]挑剔的美食家
[BZOJ1691][Usaco2007 Dec]挑剔的美食家 试题描述 与很多奶牛一样,Farmer John那群养尊处优的奶牛们对食物越来越挑剔,随便拿堆草就能打发她们午饭的日子自然是一去不返了. ...
- bzoj usaco 金组水题题解(1)
UPD:我真不是想骗访问量TAT..一开始没注意总长度写着写着网页崩了王仓(其实中午的时候就时常开始卡了= =)....损失了2h(幸好长一点的都单独开了一篇)....吓得赶紧分成两坨....TAT. ...
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
随机推荐
- luogu P3223 [HNOI2012]排队
LINK:排队\ 原谅我没学过组合数学 没有高中数学基础水平... 不过凭着隔板法的应用还是可以推出来的. 首先考虑女生 发现一个排列数m! 两个女生不能相邻 那么理论上来说存在无解的情况 而这道题好 ...
- Hadoop学习之基础环境搭建
期望目的 基于VMware workstation 10.0 + CentOS 7 + hadoop 3.2.0,在虚拟机上搭建一套Hadoop集群环境,总共包含4个节点,其中1个master节点.3 ...
- 使用VMware虚拟机建立Ubuntu与主机win7的文件共享与传输
1.要想在虚拟机与主机之间建立共享文件夹必须先安装VMware Tools.方法见https://www.cnblogs.com/lsc666js/p/13403919.html. 2.在VMware ...
- AutoMapper 9.0的改造(续)
上一篇有一个读者,有疑问,如何自动化注册Dto 我开篇,做了一个自动化注册的 public sealed class AutoInjectAttribute : Attribute { public ...
- Improving RGB-D SLAM in dynamic environments: A motion removal approach
一.贡献 (1)提出一种针对RGB-D的新的运动分割算法 (2)运动分割采用矢量量化深度图像 (3)数据集测试,并建立RGB-D SLAM系统 二.Related work [1]R.K. Namde ...
- 19-关键字package和import
1. package的使用1.1 使用说明: * 1.为了更好的实现项目中类的管理,提供包的概念 * 2.使用package声明类或接口所属的包,声明在源文件的首行 * 3.包,属于标识符,遵循标识符 ...
- SqlServer 多表连接、聚合函数、模糊查询、分组查询应用总结(回归基础)
--exists 结合 if else 以及 where 条件来使用判断是否有数据满足条件 select * from Class where Name like '%[1-3]班' if (not ...
- Android线性布局和帧布局
第二次,本牛崽十分从容,今天咱们来讲讲Android Q之布局,我遇到的问题与自己学到的,大牛不要嘲笑哈,有错误可以指出来,本牛崽看到就改了. 今天我的学长跟我们开始了布局,布局看资料说好像有5种,又 ...
- 比PS还好用!Python 20行代码批量抠图
你是否曾经想将某张照片中的人物抠出来,然后拼接到其他图片上去,从而可以即使你在天涯海角,我也可以到此一游? 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在 ...
- 【模式识别与机器学习】——PCA主成分分析
基本思想 其基本思想就是设法提取数据的主成分(或者说是主要信息),然后摒弃冗余信息(或次要信息),从而达到压缩的目的.本文将从更深的层次上讨论PCA的原理,以及Kernel化的PCA. 引子 首先我们 ...