这套好丧……跟别的画风好不一样(中国风?)。提答没做也没测,假装只有两题吧。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. JAVA使用和操作properties文件

    java中的properties文件是一种配置文件,主要用于表达配置信息,文件类型为*.properties,格式为文本文件,文件的内容是格式是"键=值"的格式,在properti ...

  2. NumPy简介

    NumPy是什么? NumPy(Numerrical Python 的缩写)是一个开源的Python科学计算库.使用NumPy,就可以很自然的使用数组.NumPy包含很多实用的数学函数,涵盖线性代数运 ...

  3. bzoj千题计划220:bzoj3938: Robot

    http://www.lydsy.com/JudgeOnline/problem.php?id=3938 以时间为x轴,以距离为y轴,那么每个机器人的行走路径就是一条折线 把折线分段加入线段树里,然后 ...

  4. python 面向对象之继承与派生

    一:初识继承 1,什么是继承? 继承指的是类与类之间的关系,是一种什么"是"什么的关系,继承的功能之一就是用来解决代码重用问题 继承是一种创建新类的方式,在python中,新建的类 ...

  5. git(一)快速入门

    1.设置用户名 git config --global user.name '你的用户名' ​ 2.设置用户名邮箱 git config --global user.email '你的邮箱' ​ 3. ...

  6. httpClient 中的post或者get请求

    httpClient相对于java自带的请求功能更加强大,下面就以例子的形式给出: //HttpClient Get请求 private static void register() { try { ...

  7. 什么是KMP算法?KMP算法推导

    花了大概3天时间,了解,理解,推理KMP算法,这里做一次总结!希望能给看到的人带来帮助!! 1.什么是KMP算法? 在主串Str中查找模式串Pattern的方法中,有一种方式叫KMP算法 KMP算法是 ...

  8. Java看书学习笔记

    1.POM:maven ,项目管理工具存放Jar包的文件2.mybatis-generator-core-1.3.2 生成文件 生成语句: java -jar mybatis-generator-co ...

  9. 深度学习之 GAN 进行 mnist 图片的生成

    深度学习之 GAN 进行 mnist 图片的生成 mport numpy as np import os import codecs import torch from PIL import Imag ...

  10. (转载) ASP.NET(C#) Web Api 通过文件流下载文件到本地实例

    下载文件到本地是很多项目开发中需要实现的一个很简单的功能.说简单,是从具体的代码实现上来说的,.NET的文件下载方式有很多种,本示例给大家介绍的是ASP.NET Web Api方式返回HttpResp ...