这套好丧……跟别的画风好不一样(中国风?)。提答没做也没测,假装只有两题吧。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的更多相关文章

  1. 【UOJ #108】【APIO 2013】TOLL

    http://uoj.ac/problem/108 好神的一道题啊. 原图边权互不相同是重点! 如果有一个点集,有两组边集,要求这两组边集的并集的最小生成树,可以对两组边集分别求一下最小生成树构成新的 ...

  2. 【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 ...

  3. 【BZOJ】【3205】【APIO2013】机器人robot

    斯坦纳树 好神啊……Orz zyf && PoPoQQQ 为啥跟斯坦纳树扯上关系了?我想是因为每个点(robot)都沿着树边汇到根的时候就全部合起来了吧= =这个好像和裸的斯坦纳树不太 ...

  4. 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 ...

  5. SharePoint 2013: A feature with ID has already been installed in this farm

    使用Visual Studio 2013创建一个可视web 部件,当右击项目选择"部署"时报错: "Error occurred in deployment step ' ...

  6. Visual Studio 2013 添加一般应用程序(.ashx)文件到SharePoint项目

    默认,在用vs2013开发SharePoint项目时,vs没有提供一般应用程序(.ashx)的项目模板,本文解决此问题. 以管理员身份启动vs2013,创建一个"SharePoint 201 ...

  7. SharePoint 2013 create workflow by SharePoint Designer 2013

    这篇文章主要基于上一篇http://www.cnblogs.com/qindy/p/6242714.html的基础上,create a sample workflow by SharePoint De ...

  8. Install and Configure SharePoint 2013 Workflow

    这篇文章主要briefly introduce the Install and configure SharePoint 2013 Workflow. Microsoft 推出了新的Workflow ...

  9. SharePoint 2013 configure and publish infopth

    This article will simply descript how to configure and publish a InfoPath step by step. Note: To con ...

随机推荐

  1. python实现京东秒杀

    # _*_coding:utf-8_*_ from selenium import webdriver import datetime import time driver = webdriver.C ...

  2. 小草手把手教你 LabVIEW 串口仪器控制——初识VISA串口

    有些人,学习一样东西时候,喜欢现成的例子.很多人学习一门技术,都喜欢现成的例子开始,比如学单片机的啊,最开始都是修改的例子吧,学语言的也是.最开始都是模仿.这个年头看书上的理论知识太浪费时间了.所以啊 ...

  3. JAVA_SE基础——60.初识Object

    java是面向对象的语言,核心思想:找适合 的对象做适合 的事情:方式一:自定义类,然后通过自定义的类创建对象.方式二:sun提供了很多的类给我使用,我们只需要认识这些类,我们就可以通过这些类创建对象 ...

  4. JAVA_SE基础——44.抽象类的练习

    抽象类要注意的细节: 1. 如果一个函数没有方法体,那么该函数必须要使用abstract修饰,把该函数修饰成抽象 的函数..2. 如果一个类出现了抽象的函数,那么该类也必须 使用abstract修饰. ...

  5. Python之旅.第三章.函数4.01/4.02

    一.三元表达式 #普通的判断大小函数def max2(x,y): if x > y: return x else: return yres=max2(10,11)print(res)x=12y= ...

  6. C# 使用 GDI+ 画图

    最近做一个微信公众号服务,有一些简单的图片处理功能.主要就是用户在页面操作,前端做一些立刻显示的效果,然后提交保存时后端真正修改原图. 我们的后端是 ASP.NET,也就是 C# 语言了,C# 本身处 ...

  7. 使用HTML5视频事件示例

    <!DOCTYPE html > <html > <head> <title>Video events example</title> &l ...

  8. emqtt 试用(三)mqtt 知识

    一.概念 MQTT 协议客户端库: https://github.com/mqtt/mqtt.github.io/wiki/libraries 例如,mosquitto_sub/pub 命令行发布订阅 ...

  9. SpringBoot入门:新一代Java模板引擎Thymeleaf(实践)

    菜鸟教程:http://www.runoob.com/ http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js http://apps.b ...

  10. Spring Security 入门(1-5)Spring Security - 匿名认证

    匿名认证 对于匿名访问的用户,Spring Security 支持为其建立一个匿名的 AnonymousAuthenticationToken 存放在 SecurityContextHolder 中, ...