APIO 2013
这套好丧……跟别的画风好不一样(中国风?)。提答没做也没测,假装只有两题吧。140/200
T1.ROBOTS
题目大意:h*w的网格上有n个机器人编号1~n,网格上有空地、墙、顺/逆时针转向器,每次可以把一个机器人朝一个方向推,机器人碰到空地会继续前进,碰到转向器会转向,碰到墙会在前一格停止,同一时间只能有一个机器人在动,编号连续的机器人可以合体,例如2号和3号合成[2,3],[2,3]和[4,6]合成[2,6],问把所有机器人合成一个最少要推几下,无解输出-1。(n<=9,h,w<=500)
思路:先记忆化搜索预处理出每个格子朝四个方向推各会推到哪里(注意可能会无限循环),用f[i][j][k][l]表示[i,j]并成一个机器人位于(k,l)格至少要推几下(内存较紧,需要hash),考虑dijkstra,堆的log难以接受,我想了个方法:答案肯定不会太大,于是每种权值开一个队列,这样复杂度是每次转移O(1),由于还要区间合并,最后时间复杂度大概是O(n^3hw),空间同样。不过实际上这个n^3不是满的,所以理论上应该是很科学的,不过我写了vector,常数好像有点大,本来想手写个链表加上内存回收搞不好就过了,因为懒而且还要打T2暴力就放弃了,最后得分85/100(都是T)。
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<queue>
using namespace std;
#define MN 500
#define MQ 11250000
struct pos{int x,y;}t[MN+][MN+][];
const int o[][]={{,-},{-,},{,},{,}};
char g[MN+][MN+];
int d[MQ+],p[][],pl[],pr[],pn,x,y,l,r;
pos work(int x,int y,int f)
{
if(t[x][y][f].x)return t[x][y][f];
t[x][y][f]=(pos){-,-};
int r;
if(g[x][y]=='.'||(g[x][y]>=''&&g[x][y]<=''))r=f;
if(g[x][y]=='A')r=f?f-:;
if(g[x][y]=='C')r=f<?f+:;
return t[x][y][f]=(g[x][y]&&g[x][y]!='x')?
work(x+o[r][],y+o[r][],r):(pos){x-o[f][],y-o[f][]};
}
inline int hash(int x,int y,int l,int r){return x<?-:((x-)*+y-)*pn+p[l][r];}
inline void dehash(int z){l=pl[z%pn];r=pr[z%pn];y=(z/=pn)%+;x=z/+;}
struct MyPQ
{
vector<queue<int> > v;int x;
void push(int x,int z)
{
if(x<||(d[x]&&d[x]<=z))return;d[x]=z;
while(v.size()<z)v.push_back(queue<int>());
v[z-].push(x);
}
inline int top(){return v[x].front();}
inline void next(){for(v[x].pop();v[x].empty()&&x<v.size();++x);if(x==v.size())puts("-1"),exit();}
inline void pop(){for(next();x>=d[v[x].front()];next());}
}q;
int main()
{
int n,w,h,i,j,k,z,zz;
scanf("%d%d%d",&n,&w,&h);--n;
for(i=;i<=h;++i)scanf("%s",g[i]+);
for(i=;i<;++i)for(j=i;j<;++j)pl[pn]=i,pr[pn]=j,p[i][j]=pn++;
for(i=;i<=h;++i)for(j=;j<=w;++j)
{
for(k=;k<;++k)work(i,j,k);
if(g[i][j]>=''&&g[i][j]<='')q.push(hash(i,j,g[i][j]-'',g[i][j]-''),);
}
while(true)
{
dehash(z=q.top());q.pop();
if(l==&&r==n)return printf("%d",d[z]-),;
for(i=;i<l;++i)if(d[zz=hash(x,y,i,l-)])q.push(hash(x,y,i,r),d[z]+d[zz]-);
for(i=;i>r;--i)if(d[zz=hash(x,y,r+,i)])q.push(hash(x,y,l,i),d[z]+d[zz]-);
for(j=;j<;++j)q.push(hash(t[x][y][j].x,t[x][y][j].y,l,r),d[z]+);
}
}
正解:双队列广搜,每种机器人先出算出可以合成它的所有小机器人在各个位置的情况,然后开两个队列,一个是按从小机器人合成的按权值排序的队列,一个是被推着走拓展出的队列,每次取最小的,这种做法理论上和我的是同阶的,不过常数上感觉比我优到不知道哪里去了。
T2.TOLL
题目大意:给出一张N点M边的带权联通无向图,每个点上有一些人,给定K条边,要求你定边权后加入原图,使得最后最小生成树上,每个人走到1号点,路径上经过的新加的边的权值和最大。(N<=100,000,M<=300,000,K<=20)
思路:暴力枚举最后保留哪些新加的边,对原图做最小生成树后,每次加入一条非树边,O(n)算出每条边被保留下最大能取的权值,并算出答案,复杂度O(MlogM+NK*2^K),得分55/100。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
inline int read()
{
int x=;char c;
while((c=getchar())<''||c>'');
for(;c>=''&&c<='';c=getchar())x=(x<<)+(x<<)+c-'';
return x;
}
#define MN 100000
#define MM 300000
#define MK 20
struct Edge{int x,y,w;}E[MM+],S[MN+],K[MK+],T[MN+];
bool cmp(Edge a,Edge b){return a.w<b.w;}
struct edge{int nx,t,w,u,f;}e[MN*+];
int n,k,f[MN+],h[MN+],en,u[MN+],p[MN+],mx[MK+];
int fa[MN+],tf[MN+],d[MN+],ps[MN+];
ll ans,fs[MN+];
int gf(int k){return f[k]?f[k]=gf(f[k]):k;}
inline void ins(int x,int y,int w,int f=)
{
e[++en]=(edge){h[x],y,w,,f};h[x]=en;
e[++en]=(edge){h[y],x,w,,f};h[y]=en;
}
void pre(int x)
{
for(int i=h[x];i;i=e[i].nx)if(!e[i].u&&e[i].t!=fa[x])
d[e[i].t]=d[x]+,fa[e[i].t]=x,tf[e[i].t]=i,pre(e[i].t);
}
void dp(int x,int fa)
{
ps[x]=p[x];fs[x]=;
for(int i=h[x];i;i=e[i].nx)if(!e[i].u&&e[i].t!=fa)
{
dp(e[i].t,x);
ps[x]+=ps[e[i].t];
fs[x]+=fs[e[i].t];
if(e[i].f)fs[x]+=(ll)mx[e[i].f]*ps[e[i].t];
}
}
void work()
{
int i,j=,x,y,z,c;
memset(f,,sizeof(int)*(n+));
for(i=;i<=k;++i)if(u[i]&&gf(K[i].x)!=gf(K[i].y))
f[gf(K[i].x)]=gf(K[i].y),T[++j]=K[i];
memset(h,,sizeof(int)*(n+));en=;
for(i=;i<n;++i)ins(S[i].x,S[i].y,S[i].w);
memset(mx,,sizeof(mx));
for(i=;i<=j;++i)
{
pre();
for(x=T[i].x,y=T[i].y,z=-;x!=y;)
if(d[x]>d[y]){if(e[tf[x]].w&&e[tf[x]].w>z)z=e[tf[x]].w,c=tf[x];x=fa[x];}
else{if(e[tf[y]].w&&e[tf[y]].w>z)z=e[tf[y]].w,c=tf[y];y=fa[y];}
e[c].u=e[c^].u=;mx[i]=z;
for(x=T[i].x,y=T[i].y;x!=y;)
if(d[x]>d[y]){if(!e[tf[x]].w)mx[e[tf[x]].f]=min(mx[e[tf[x]].f],z);x=fa[x];}
else{if(!e[tf[y]].w)mx[e[tf[y]].f]=min(mx[e[tf[y]].f],z);y=fa[y];}
ins(T[i].x,T[i].y,,i);
}
dp(,);
if(fs[]>ans)ans=fs[];
}
void dfs(int x)
{
if(x>k){work();return;}
u[x]=;dfs(x+);
u[x]=;dfs(x+);
}
int main()
{
freopen("toll.in","r",stdin);
freopen("toll.out","w",stdout);
int m,i,j;
n=read();m=read();k=read();
for(i=;i<m;++i)E[i].x=read(),E[i].y=read(),E[i].w=read();
sort(E,E+m,cmp);
for(i=j=;i<m;++i)if(gf(E[i].x)!=gf(E[i].y))
f[gf(E[i].x)]=gf(E[i].y),S[++j]=E[i];
for(i=;i<=k;++i)K[i].x=read(),K[i].y=read();
for(i=;i<=n;++i)p[i]=read();
dfs();
cout<<ans;
fclose(stdin);fclose(stdout);return ;
}
正解:一开始先把K条边边权设为0和M条边放一起跑最小生成树,K条边把最小生成树分成K+1块,每一块最后无论如何一定是连在一起的,可以缩成一个点,然后再按上面的暴力做,复杂度O(MlogM+K^2*2^K)。
APIO 2013的更多相关文章
- 【UOJ #108】【APIO 2013】TOLL
http://uoj.ac/problem/108 好神的一道题啊. 原图边权互不相同是重点! 如果有一个点集,有两组边集,要求这两组边集的并集的最小生成树,可以对两组边集分别求一下最小生成树构成新的 ...
- 【UOJ #107】【APIO 2013】ROBOTS
http://uoj.ac/problem/107 设\(f(l,r,i,j)\)表示\([l,r]\)中的机器人聚集到\((i,j)\)需要花的最小操作数. \(f(l,r,i,j)=\min\le ...
- 【BZOJ】【3205】【APIO2013】机器人robot
斯坦纳树 好神啊……Orz zyf && PoPoQQQ 为啥跟斯坦纳树扯上关系了?我想是因为每个点(robot)都沿着树边汇到根的时候就全部合起来了吧= =这个好像和裸的斯坦纳树不太 ...
- 2013 Asia Changsha Regional Contest---Josephina and RPG(DP)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=4800 Problem Description A role-playing game (RPG and ...
- SharePoint 2013: A feature with ID has already been installed in this farm
使用Visual Studio 2013创建一个可视web 部件,当右击项目选择"部署"时报错: "Error occurred in deployment step ' ...
- Visual Studio 2013 添加一般应用程序(.ashx)文件到SharePoint项目
默认,在用vs2013开发SharePoint项目时,vs没有提供一般应用程序(.ashx)的项目模板,本文解决此问题. 以管理员身份启动vs2013,创建一个"SharePoint 201 ...
- SharePoint 2013 create workflow by SharePoint Designer 2013
这篇文章主要基于上一篇http://www.cnblogs.com/qindy/p/6242714.html的基础上,create a sample workflow by SharePoint De ...
- Install and Configure SharePoint 2013 Workflow
这篇文章主要briefly introduce the Install and configure SharePoint 2013 Workflow. Microsoft 推出了新的Workflow ...
- SharePoint 2013 configure and publish infopth
This article will simply descript how to configure and publish a InfoPath step by step. Note: To con ...
随机推荐
- python的Flask 介绍
Flask 介绍 知识点 微框架.WSGI.模板引擎概念 使用 Flask 做 web 应用 模板的使用 根据 URL 返回特定网页 实验步骤 1. 什么是 Flask? Flask 是一个 web ...
- 2017 国庆湖南 Day5
期望得分:76+80+30=186 实际得分:72+10+0=82 先看第一问: 本题不是求方案数,所以我们不关心 选的数是什么以及的选的顺序 只关心选了某个数后,对当前gcd的影响 预处理 cnt[ ...
- JAVA_SE基础——46.引用数据类型变量.值交换[独家深入解析]
需求:定义一个函数交换数组中两个元素的位置. code 1: import java.util.*; class Demo3 { public static void main(String[] ar ...
- New UWP Community Toolkit - RotatorTile
概述 UWP Community Toolkit 中有一个为图片或磁贴提供轮播效果的控件 - RotatorTile,本篇我们结合代码详细讲解 RotatorTile 的实现. RotatorTi ...
- angluarjs2入门学习资源
http://www.runoob.com/angularjs2/angularjs2-tutorial.htmlhttps://segmentfault.com/a/1190000008423981 ...
- Nginx负载均衡(架构之路)
[前言] 在大型网站中,负载均衡是有想当必要的.尤其是在同一时间访问量比较大的大型网站,例如网上商城,新闻等CMS系统,为了减轻单个服务器的处理压力,我们引进了负载均衡这一个概念,将一个服务器的压力分 ...
- Python系列-python函数
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但你也可以自己创建函数,这 ...
- android studio 何如修改报名
1. 重命名办法,网上很多见 2. 对于需要重新修改包名的级别的 a. 修改package 和 gradle 的包名,对应一致. b. 修改R 所在包名,使用crtl+n修改R文件的路径 c. 手动首 ...
- UVA850【简单模拟】
题目:解密句子.有一些被加密的句子已知一条模板翻译,判断是否可以解密,可以的话将所有句子解密. #include <stdio.h> #include<iostream> #i ...
- python/数据类型和变量
数据类型和变量 数据类型 计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值.但是, 计算机能处理的远不止数值,还可以处理文本.图形.音频.视频.网页等各种各样的数据, ...