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) ...
随机推荐
- web移动端开发经验总结
整理web移动端开发经验,部分内容借鉴于网上的博文. 1.meta标签 <meta name="viewport" content="width=device-wi ...
- spring中的BeanFactory与ApplicationContext的作用和区别
BeanFactory 和ApplicationContext Bean 工厂(com.springframework.beans.factory.BeanFactory)是Spring 框架最核心的 ...
- Celery 分布式任务队列入门
一.Celery介绍和基本使用 Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery ...
- router-link params传参
1.router.js配置 需要在路径后定义上要传的属性名 --> /:属性名(query方式不需要) { path: '/CreateProgress/:name1', name: ...
- 【pyqt5】QdateTimeEdit(日期时间)
返回当前日期和时间设置 from PyQt5 import QtCore, QtWidgets class Ui_Dialog(object): def setupUi(self, Dialog): ...
- Pycharm自动换行
只对当前文件有效的操作是菜单栏->View -> Active Editor -> Use Soft Wraps. 要是想对所有文件都起到效果,就要在setting里面进行操作.Pe ...
- sql批量修改wordpress网站的文章发布状态
wordpress批量导入文章的时候,有些文章的状态可能会缺失,例如“mis scheduled”.draft.future等几种状态,如何用sql批量修改wordpress网站的文章发布状态呢? 点 ...
- Sqoop导入HBase,并借助Coprocessor协处理器同步索引到ES
1.环境 Mysql 5.6 Sqoop 1.4.6 Hadoop 2.5.2 HBase 0.98 Elasticsearch 2.3.5 2.安装(略过) 3.HBase Coprocessor实 ...
- Matlab中图像处理实例:灰度变换,空域滤波,频域滤波,傅里叶变换的实现
http://blog.sciencenet.cn/blog-95484-803140.html % %图像灰度变换 % f = imread('E:\2013第一学期课程\媒体计算\实验一\Img\ ...
- liferay总结的通用的工具类
在写增删改查的时候,自己动手写了几个通用的工具类,这几个通用的工具类也是基于API写的 第一个是liferay中的分页.跟我们做普通的web开发,分页是一样的首先需要建立一个分页的实体的类 packa ...