noip杂题题解
这道题没有什么可说的,先统计,然后几次快排,答案就出来了
Code(整齐但不简洁的代码)
#include<iostream>
#include<cstdio>
#include<fstream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
typedef bool boolean;
template<typename T>
inline void readInteger(T& u){
char x;
while(!isdigit((x = getchar())));
for(u = x - ''; isdigit((x = getchar())); u = (u << ) + (u << ) + x - '');
ungetc(x, stdin);
}
int m, n;
int k, l;
int d;
typedef class Point{
public:
int x;
int y;
Point(const int x = , const int y = ):x(x), y(y){}
boolean operator <(Point another) const{
if(this->x != another.x) return this->x < another.x;
return this->y < another.y;
}
}Point;
inline Point readPoint(){
Point a;
readInteger(a.x);
readInteger(a.y);
return a;
}
typedef class MyData{
public:
int num;
int count;
MyData(const int num = ):num(num){}
}MyDatas;
MyData *c_r;
MyData *c_l;
inline void init(){
readInteger(m);
readInteger(n);
readInteger(k);
readInteger(l);
readInteger(d);
c_r = new MyData[(const int)(m + )];
c_l = new MyData[(const int)(n + )];
memset(c_r, , sizeof(MyData) * (m + ));
memset(c_l, , sizeof(MyData) * (n + ));
for(int i = ; i <= m; i++) c_r[i].num = i;
for(int i = ; i <= n; i++) c_l[i].num = i;
for(int i = ; i <= d; i++){
Point a = readPoint();
Point b = readPoint();
Point s = min(a, b);
if(a.x == b.x){
c_l[s.y].count++;
}else c_r[s.x].count++;
}
}
boolean cmpare(const MyData &a, const MyData &b){
return a.count > b.count;
}
boolean cmpare2(const MyData &a, const MyData &b){
return a.num < b.num;
}
inline void solve(){
sort(c_l + , c_l + n + , cmpare);
sort(c_r + , c_r + m + , cmpare);
sort(c_l + , c_l + l + , cmpare2);
sort(c_r + , c_r + k + , cmpare2);
for(int i = ; i <= k; i++){
printf("%d ", c_r[i].num);
}
putchar('\n');
for(int i = ; i <= l; i++){
printf("%d ", c_l[i].num);
}
}
int main(){
freopen("seat.in", "r", stdin);
freopen("seat.out", "w", stdout);
init();
solve();
return ;
}
这道题是有依赖的背包问题的裸题,一个主件最多有两个附件,而且附件没有属自己的附件,所以不用考虑树形dp
直接用普通的dp就行了,考虑4个状态
1)只要主件
2)只要主件和第一个附件
3)只要主件和第二个附件
4)要主件和它的两个附件
如果某个主件的第二个附件不存在呢?不管,不会影响答案,如果特判的话很耗代码。
如果dp到附件怎么办?不管,直接跳过
如果你希望运行的速度更快,可以将n和每个v除以10,最后结果乘上10
Code(极其不简洁的代码)
#include<iostream>
#include<cstdio>
#include<fstream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
///template starts
typedef bool boolean;
template<typename T>
inline void readInteger(T& u){
char x;
while(!isdigit((x = getchar())));
for(u = x - ''; isdigit((x = getchar())); u = (u << ) + (u << ) + x - '');
ungetc(x, stdin);
}
///template ends
int n;
int m;
int *v;
int *w;
int *son[];
int f[];
int result;
boolean *seced;
inline void init(){
readInteger(n);
readInteger(m);
n /= ;
v = new int[(const int)(m + )];
w = new int[(const int)(m + )];
son[] = new int[(const int)(m + )];
son[] = new int[(const int)(m + )];
seced = new boolean[(const int)(m + )];
memset(seced, false, sizeof(boolean) * (m + ));
memset(son[], , sizeof(int) * (m + ));
memset(son[], , sizeof(int) * (m + ));
for(int i = , a; i <= m; i++){
readInteger(v[i]);
v[i] /= ;
readInteger(w[i]);
readInteger(a);
if(a == ) seced[i] = true;
if(son[][a] == ) son[][a] = i;
else son[][a] = i;
}
}
inline void solve(){
seced[] = true;
v[] = w[] = ;
for(int i = ; i <= m; i++){
if(seced[i]){
for(int j = n; j >= v[i]; j--){
f[j] = max(f[j - v[i]] + v[i] * w[i], f[j]);
int s = ;
int sv = ;
for(int k = ; k < ; k++){
int r = v[son[k][i]] * w[son[k][i]];
s += r;
sv += v[son[k][i]];
if(j >= v[i] + v[son[k][i]]){
f[j] = max(f[j - v[i] - v[son[k][i]]] + v[i] * w[i] + r, f[j]);
}
}
if(j >= v[i] + sv){
f[j] = max(f[j - v[i] - sv] + v[i] * w[i] + s, f[j]);
}
}
}
}
printf("%d", f[n] * );
}
int main(){
freopen("budget.in", "r", stdin);
freopen("budget.out", "w", stdout);
init();
solve();
return ;
}
这题有两个比较常见的做法,我只写其中一个,但还是都说说
1)Tarjan + 拓扑
首先用Tarjan将所有的环(强连通分量)求出来,缩成一个点,求出它的最大值和最小值
接着从起点开始,进行拓扑排序,求出答案
2)spfa
首先可以枚举一个断点,为了使答案最大,所以从起点到断点找到一个最小值,再从终点
到起点找到一个最大值,在这个最小值这个点买入,在最大值这个点卖出,用最大值减最小值
求出这个差价。
如果每个断点都去跑两次spfa肯定会超时,所以就先用两次spfa预处理,第一次spfa在原
先的图上求出从起点出发,到i这个点的最短“距”,再从反向图中,从终点开始求出到点i这个点
的最长“距”
Code(比较复杂的代码)
#include<iostream>
#include<cstdio>
#include<fstream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
///template starts
typedef bool boolean;
template<typename T>
inline void readInteger(T& u){
char x;
while(!isdigit((x = getchar())));
for(u = x - ''; isdigit((x = getchar())); u = (u << ) + (u << ) + x - '');
ungetc(x, stdin);
}
typedef class Edge{
public:
int end;
int next;
Edge(const int end = , const int next = ):end(end), next(next){}
}Edge;
typedef class MapManager{
public:
int ce;
int *h;
Edge *edge;
MapManager():ce(), h(NULL), edge(NULL){}
MapManager(int limit, int points):ce(){
h = new int[(const int)(points + )];
edge = new Edge[(const int)(limit + )];
memset(h, , sizeof(int) * (points + ));
}
inline void addEdge(int from, int end){
edge[++ce] = Edge(end, h[from]);
h[from] = ce;
}
}MapManager;
///template ends
int n, m;
int getData(boolean (*cmpare)(const int&, const int&), int a, int b){
if((*cmpare)(a, b)) return a;
return b;
}
int *prices;
inline void spfa(MapManager& g, int start, int end, int *f, boolean* visited, boolean (*cmpare)(const int&, const int&)){
memset(visited, false, sizeof(boolean) * (n + ));
queue<int> que;
que.push(start);
visited[start] = true;
while(!que.empty()){
int u = que.front();
que.pop();
visited[u] = false;
for(int i = g.h[u]; i != ; i = g.edge[i].next){
int eu = g.edge[i].end;
int d = getData(cmpare, f[u], prices[eu]);
if((*cmpare)(d, f[eu])){
f[eu] = d;
if(!visited[eu]){
que.push(eu);
visited[eu] = true;
}
}
}
}
}
MapManager g;
MapManager rev_g;
int *maxdis;
int *mindis;
boolean *visited;
boolean _min(const int &a, const int &b){ return a < b; }
boolean _max(const int &a, const int &b){ return a > b; }
inline void init(){
readInteger(n);
readInteger(m);
g = MapManager(m * , n);
rev_g = MapManager(m * , n);
prices = new int[(const int)(n + )];
maxdis = new int[(const int)(n + )];
mindis = new int[(const int)(n + )];
visited = new boolean[(const int)(n + )];
memset(maxdis, , sizeof(int) * (n + ));
memset(mindis, 0x7f, sizeof(int) * (n + ));
for(int i = ; i <= n; i++)
readInteger(prices[i]);
for(int i = , a, b, c; i <= m; i++){
readInteger(a);
readInteger(b);
readInteger(c);
g.addEdge(a, b);
rev_g.addEdge(b, a);
if(c == ){
g.addEdge(b, a);
rev_g.addEdge(a, b);
}
}
}
inline void solve(){
spfa(g, , n, mindis, visited, _min);
spfa(rev_g, n, , maxdis, visited, _max);
int result = ;
for(int i = ; i < n; i++){
result = max(result, maxdis[i] - mindis[i]);
}
printf("%d", result);
}
int main(){
freopen("trade.in", "r", stdin);
freopen("trade.out", "w", stdout);
init();
solve();
return ;
}
(ps:为了防止写两遍spfa,所以一次spfa写得比较复杂)
noip杂题题解的更多相关文章
- 贪心/构造/DP 杂题选做Ⅲ
颓!颓!颓!(bushi 前传: 贪心/构造/DP 杂题选做 贪心/构造/DP 杂题选做Ⅱ 51. CF758E Broken Tree 讲个笑话,这道题是 11.3 模拟赛的 T2,模拟赛里那道题的 ...
- 【入门OJ】2003: [Noip模拟题]寻找羔羊
这里可以复制样例: 样例输入: agnusbgnus 样例输出: 6 这里是链接:[入门OJ]2003: [Noip模拟题]寻找羔羊 这里是题解: 题目是求子串个数,且要求简单去重. 对于一个例子(a ...
- NOIP模拟题汇总(加厚版)
\(NOIP\)模拟题汇总(加厚版) T1 string 描述 有一个仅由 '0' 和 '1' 组成的字符串 \(A\),可以对其执行下列两个操作: 删除 \(A\)中的第一个字符: 若 \(A\)中 ...
- 历年NOIP真题总结
前言:最近把历年的NOIP真题肝了一遍(还有3个紫题先咕掉了),主要是到1998年的提高组的题.把题目的做题简要思路搁在这儿,一个是为了考前翻一翻,想想自己的哪些思路要梳理的什么什么的,反正怎么说呢, ...
- NOIP原题 斗地主(20190804)
题目描述 牛牛最近迷上了一种叫斗地主的扑克游戏.斗地主是一种使用黑桃.红心.梅花.方片的A到K加上大小王的共54张牌来进行的扑克牌游戏.在斗地主中,牌的大小关 系根据牌的数码表示如下:3<4&l ...
- dp杂题(根据个人进度选更)
----19.7.30 今天又开了一个新专题,dp杂题,我依旧按照之前一样,这一个专题更在一起,根据个人进度选更题目; dp就是动态规划,本人认为,动态规划的核心就是dp状态的设立以及dp转移方程的推 ...
- wangkoala杂题总集(根据个人进度选更)
CQOI2014 数三角形 首先一看题,先容斥一波,求出网格内选三个点所有的情况,也就是C(n*m,3);然后抛出行里三点共线的方案数:C(n,3)*m; 同理就有列中三点共线的方案数:n*C(m,3 ...
- Educational Codeforces Round 53 (Rated for Div. 2) (前五题题解)
这场比赛没有打,后来补了一下,第五题数位dp好不容易才搞出来(我太菜啊). 比赛传送门:http://codeforces.com/contest/1073 A. Diverse Substring ...
- Codeforces 杂题集 2.0
记录一些没有写在其他随笔中的 Codeforces 杂题, 以 Problemset 题号排序 1326D2 - Prefix-Suffix Palindrome (Hard version) ...
随机推荐
- 安装XP时BIOS的设置(ahci ide)
和以前使用Windows XP一样,很多用户都在设法提高Windows 7的系统运行速速,比较常见的方法大多是对系统服务进行优化,去掉一些可有可无的系统服务,还有就是优化资源管理器菜单等.除此之外,还 ...
- lamp docker apache2 supervisor monitor
sudo docker run -d -p 80:80 -p 3306:3306 -v /data/lampp/supervisormonitor:/app --name mylamp01 tutum ...
- Linux的/etc/services文件的作用?
4)端口分配 Linux系统的端口号的范围为0–65535,不同范围有不同的意义. 0 不使用 1--1023 系统保留,只能由root用户使用 1024---4999 由客户端程序自由分配 5000 ...
- pdb学习笔记
参考资料:https://segmentfault.com/a/1190000006628456 下一行(不进入函数内部):n(ext) 单步(进入函数内部):s(tep) 打印:p 动态添加断点:1 ...
- struts2 OGNL(Object-Graph Navigation Language) 井号,星号,百分号
1.“#”主要有三种用途: 访问OGNL上下文和Action上下文,#相当于ActionContext.getContext():可以访问这几个ActionContext中的属性. parameter ...
- javascript php 数组 json 对比 总结
看到这个博客,终于明白JavaScript 里只有一种 Array,不存在索引数组和关联数组. 1.在js中所有要素都是继承自Object对象的,任何对象都能通过obj["name" ...
- li设置float后ul无法包裹li问题解决
解决办法:灰常简单,只需给ul添加样式 ul{ overflow: auto; } 即可
- Shell初学(一)hello world
精简: 1.创建:可以使用 vi/vim 命令来创建文件如: test.sh ,扩展名并不影响脚本执行,写什么都可以. 2.hello_world: #!/bin/bash ...
- 007-jdk1.6版本新特性
一.JDK1.6 名称:Mustang(野马) 发布日期:2006-04 新特性: 1.1.AWT新增加了两个类:Desktop和SystemTray[忽略] 前者可以用来打开系统默认浏览器浏览指定的 ...
- 高性能mysql 第1,2,3章。
一: 第一章 1:使用事务 start transaction; select * from t1; commit; 2:查看事务状态 mysql> show variables like 'a ...