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

    1.下载QT5 SDK 下载地址:http://qt-project.org/downloads. 2.安装QT5 下载完后,假设放在Download/,切换到该目录,输入:./qt-linux-op ...

  2. jQuery 写的textarea输入字数限制

    //先判断浏览器是不是万恶的IE        var bind_name = 'input';//默认事件        if (navigator.userAgent.indexOf(" ...

  3. js前端对后台数据的获取,如果是汉字则需要添上引号

    js前端对后台数据的获取,如果是汉字则需要添上引号

  4. DDD实战进阶第一波(二):开发一般业务的大健康行业直销系统(搭建支持DDD的轻量级框架一)

    要实现软件设计.软件开发在一个统一的思想.统一的节奏下进行,就应该有一个轻量级的框架对开发过程与代码编写做一定的约束. 虽然DDD是一个软件开发的方法,而不是具体的技术或框架,但拥有一个轻量级的框架仍 ...

  5. JQ 标签相关知识

    1.判断 checkbox 和 radio 是否选中 if($("标签选择器").is(":checked")) 2.改变 checkbox 选中状态 .pro ...

  6. Mysql编译安装详解

    wget http://mirrors.cnnic.cn/apache/httpd/mysql-5.5.20.tar.gz root@Mysql-server ~]# yum install -y c ...

  7. 算法题丨Move Zeroes

    描述 Given an array nums, write a function to move all 0's to the end of it while maintaining the rela ...

  8. 新概念英语(1-3)Sorry, sir

    Does the man get his umbrella back? A:My coat and my umbrella please. B:Here is my ticket. A:Thank y ...

  9. python-3.x-基本数据类型

    当前学习版本为: python-3.6-4 代码: """整型 NUMBER""" a = 2 ** 5 b = a + 4 c = a / ...

  10. Apache Flink 分布式执行

    Flink 的分布式执行过程包含两个重要的角色,master 和 worker,参与 Flink 程序执行的有多个进程,包括 Job Manager,Task Manager 以及 Job Clien ...