题目背景

班级聚会的时候,班主任为了方便管理,规定吃饭的时候同一个寝室的同学必须坐在一起;但是吃完饭后,到了娱乐时间,喜欢不同游戏的同学会聚到一起;在这个过程中就涉及到了座位分配的问题。

题目描述

有 n 张圆桌排成一排(从左到右依次编号为 0 到 n−1 ),每张桌子有 m 个座位(按照逆时针依次编号为 0到 m−1 ),在吃饭时每个座位上都有一个人;在吃完饭后的时候,每个人都需要选择一个新的座位(新座位可能和原来的座位是同一个),具体来说,第 i 桌第 j 个人的新座位只能在第 Li,j 桌到第 Ri,j 桌中选,可以是这些桌中的任何一个座位。确定好新座位之后,大家开始移动,移动的体力消耗按照如下规则计算:

移动座位过程分为两步:

  1. 从起始桌移动到目标桌对应座位,这个过程中的体力消耗为两桌距离的两倍,即从第 i 桌移动到第 j 桌对应座位的体力消耗为 2×|i−j|;

2.从目标桌的对应座位绕着桌子移动到目标座位,由于桌子是圆的,所以客人会选择最近的方向移动,体力消耗为移动距离的一倍,即从编号为 x 的座位移动的编号为 y 的座位的体力消耗为 min(|x−y|,m−|x−y|);

详情如下图:

现在,给定每个客人的限制(即每个人的新座位所在的区间),需要你设计一个方案,使得所有客人消耗的体力和最小;本题中假设客人在移动的时候互不影响。

输入格式

从标准输入读入数据。

第一行输入两个数 n 和 m;

接下来输入 n 行,每行 m 个空格隔开的整数描述矩阵 L:其中,第 i 行的第 j 个数表示 Li,j;

接下来输入 n 行,每行 m 个空格隔开的整数描述矩阵 R:其中,第 i 行的第 j 个数表示 Ri,j。

输出格式

输出到标准输出。

输出总体力消耗的最小值,如果没有合法的方案输出no solution

  • 题解:

    • 由原来的人向现在的每个可达的位置连边桌子连边做费用流($zkw$)有70;
    • 设源$S$,汇$T$,原来的人为$s_{ij}$,现在的位置为$t_{ij}$,同桌之间移动的代价$c1$,不同桌的为$c2$;
    • 这题的一大特点就是原来的人向现在的对应位置的连边是区间$[L_{i,j},R_{i,j}]$;
    • 考虑用线段树优化建边,就是所有的$s_{i,j}$点先连向线段树,再连向$t_{i,j}$;
    • 由于要共用线段树的节点所以需要对代价$c2$做一些转化;
    • 将$t$拆成$t1$和$t2$分别表示不同桌向左走或向右走,$S$连向$s_{i,j}$代价$i*2$ ,$t1$,$t2$连向$T$代价$-i*2$;
    • 建两颗线段树,叶子节点分别连向$t1$和$t2$,区间[L,R]拆成[L,i]和[i,R]即可向线段树节点连边;
    • 节点个数$O(3*nm + 8*nm)$,边数$O( 3*nm + 4*nm + 8*nm + logn * nm)$
    •  #include<bits/stdc++.h>
      #define inf 0x3f3f3f3f
      using namespace std;
      const int N=,K=;
      int S,T,n,m,o,hd[N],dis[N],vis[N],sum1[K],sum2[K];
      int id1[K][K],id2[K][K],id3[K][K],id4[K][K],L[K][K],R[K][K];
      struct Edge{int v,nt,f,w;}E[N<<];
      void adde(int u,int v,int f,int w){
      E[o]=(Edge){v,hd[u],f,w};hd[u]=o++;
      E[o]=(Edge){u,hd[v],,-w};hd[v]=o++;
      }
      queue<int>q;
      bool bfs(){
      memset(vis,,sizeof(vis));
      memset(dis,0x3f,sizeof(dis));
      q.push(T);dis[T]=;vis[T]=;
      while(!q.empty()){
      int u=q.front();q.pop();
      vis[u]=;
      for(int i=hd[u];~i;i=E[i].nt)if(E[i^].f){
      int v=E[i].v;
      if(dis[v]>dis[u]+E[i^].w){
      dis[v]=dis[u]+E[i^].w;
      if(!vis[v])vis[v]=,q.push(v);
      }
      }
      }
      return dis[S]!=inf;
      }
      int dfs(int u,int F){
      vis[u]=;
      if(u==T||!F)return F;
      int flow=,f;
      for(int i=hd[u];~i;i=E[i].nt){
      int v=E[i].v;
      if(!vis[v]&&dis[v]+E[i].w==dis[u]&&E[i].f&&(f=dfs(v,min(F,E[i].f)))){
      flow+=f;F-=f;
      E[i].f-=f,E[i^].f+=f;
      if(!F)break;
      }
      }
      return flow;
      }
      int zkw(){
      int flow=,cost=,f;
      while(bfs()){
      do{
      memset(vis,,sizeof(vis));
      f=dfs(S,inf);
      flow+=f;
      cost+=dis[S]*f;
      }while(vis[T]);
      }
      return flow==n*m?cost:-;
      }
      int main(){
      // freopen("C.in","r",stdin);
      // freopen("C.out","w",stdout);
      memset(hd,-,sizeof(hd));
      scanf("%d%d",&n,&m);
      for(int i=;i<=n;i++)
      for(int j=;j<=m;j++){
      id1[i][j]=(i-)*m+j;
      id2[i][j]=n*m+id1[i][j];
      id3[i][j]=n*m+id2[i][j];
      id4[i][j]=n*m+id3[i][j];
      }
      S=,T=id4[n][m]+;
      for(int i=;i<=n;i++){
      for(int j=;j<=m;j++){
      adde(S,id1[i][j],,);
      adde(id2[i][j],id4[i][j],,);
      adde(id3[i][j],id4[i][j],,);
      adde(id4[i][j],T,,);
      int ri=j%m+,le=(j+m-)%m+;
      adde(id2[i][j],id2[i][ri],inf,);
      adde(id2[i][j],id2[i][le],inf,);
      adde(id3[i][j],id3[i][ri],inf,);
      adde(id3[i][j],id3[i][le],inf,);
      if(i>)adde(id2[i][j],id2[i-][j],inf,);
      if(i<n)adde(id3[i][j],id3[i+][j],inf,);
      }
      }
      for(int i=;i<=n;i++)
      for(int j=;j<=m;j++){scanf("%d",&L[i][j]);sum2[++L[i][j]]++;}
      for(int i=;i<=n;i++)
      for(int j=;j<=m;j++){scanf("%d",&R[i][j]);sum1[++R[i][j]]++;}
      for(int i=;i<=n;i++){
      sum1[i]+=sum1[i-];
      if(sum1[i]>i*m)return puts("no solution"),;
      }
      for(int i=n;i>=;i--){
      sum2[i]+=sum2[i+];
      if(sum2[i]>(n-i+)*m)return puts("no solution"),;
      }
      for(int i=;i<=n;i++)
      for(int j=;j<=m;j++){
      if(L[i][j]<=i&&i<=R[i][j])adde(id1[i][j],id2[i][j],,),adde(id1[i][j],id3[i][j],,);
      else if(i<L[i][j])adde(id1[i][j],id3[L[i][j]][j],,(L[i][j]-i)<<);
      else adde(id1[i][j],id2[R[i][j]][j],,(i-R[i][j])<<);
      }
      int ans = zkw();
      if(!~ans)puts("-1");
      else printf("%d\n",ans);
      return ;
      }

      70pts

    •  #include<bits/stdc++.h>
      #define inf 0x3f3f3f3f
      #define il inline
      #define ID(i,j) (i-1)*m+j
      using namespace std;
      const int N=,M=;
      int n,m,L[][],R[][],ls1[],rs1[],ls2[],rs2[],cnt,rt1,rt2;
      int S,T,o,hd[N],vis[N],dis[N],id1[],id2[],q[N],head,tail;
      struct Edge{int v,nt,f,w;}E[M<<];
      il void adde(int u,int v,int f,int w){
      // printf("%d %d %d %d\n",u,v,f,w);
      E[o]=(Edge){v,hd[u],f,w};hd[u]=o++;
      E[o]=(Edge){u,hd[v],,-w};hd[v]=o++;
      }
      il void Adde(int u,int v,int f,int w){
      for(int i=;i<=m;i++)adde(ID(u,i),ID(v,i),f,w);
      }
      void build1(int&k,int l,int r){
      k=++cnt;
      if(l==r){Adde(k,id2[l],inf,-*l);return;}
      int mid=(l+r)>>;
      build1(ls1[k],l,mid);
      build1(rs1[k],mid+,r);
      Adde(k,ls1[k],inf,);
      Adde(k,rs1[k],inf,);
      }
      void build2(int&k,int l,int r){
      k=++cnt;
      if(l==r){Adde(k,id2[l],inf,-*(n-l+));return;}
      int mid=(l+r)>>;
      build2(ls2[k],l,mid);
      build2(rs2[k],mid+,r);
      Adde(k,ls2[k],inf,);
      Adde(k,rs2[k],inf,);
      }
      void update1(int k,int l,int r,int x,int y,int i,int j,int val){
      if(l==x&&r==y){adde(ID(id1[i],j),ID(k,j),inf,val);}
      else{
      int mid=(l+r)>>;
      if(y<=mid)update1(ls1[k],l,mid,x,y,i,j,val);
      else if(x>mid)update1(rs1[k],mid+,r,x,y,i,j,val);
      else update1(ls1[k],l,mid,x,mid,i,j,val),update1(rs1[k],mid+,r,mid+,y,i,j,val);
      }
      }
      void update2(int k,int l,int r,int x,int y,int i,int j,int val){
      if(l==x&&r==y){adde(ID(id1[i],j),ID(k,j),inf,val);}
      else{
      int mid=(l+r)>>;
      if(y<=mid)update2(ls2[k],l,mid,x,y,i,j,val);
      else if(x>mid)update2(rs2[k],mid+,r,x,y,i,j,val);
      else update2(ls2[k],l,mid,x,mid,i,j,val),update2(rs2[k],mid+,r,mid+,y,i,j,val);
      }
      }
      bool spfa(){
      for(int i=;i<=cnt*m;i++)vis[i]=,dis[i]=inf;
      head=tail=;dis[q[tail++]=T]=;
      while(head!=tail){
      int u=q[head++];if(head==N)head=;
      vis[u]=;
      for(int i=hd[u];~i;i=E[i].nt)if(E[i^].f){
      int v=E[i].v;
      if(dis[v]>dis[u]+E[i^].w){
      dis[v]=dis[u]+E[i^].w;
      if(!vis[v]){
      vis[v]=,q[tail++]=v;
      if(tail==N)tail=;
      }
      }
      }
      }
      return dis[S]!=inf;
      }
      int dfs(int u,int F){
      vis[u]=;
      if(u==T||!F)return F;
      int flow=,f;
      for(int i=hd[u];~i;i=E[i].nt){
      int v=E[i].v;
      if(E[i].f&&!vis[v]&&dis[v]+E[i].w==dis[u]&&(f=dfs(v,min(F,E[i].f)))){
      flow+=f,F-=f;
      E[i].f-=f,E[i^].f+=f;
      if(!F)break;
      }
      }
      return flow;
      }
      int zkw(){
      int flow=,cost=,f;
      while(spfa()){
      do{
      for(int i=;i<=cnt*m;i++)vis[i]=;
      f=dfs(S,inf);
      flow+=f;
      cost+=dis[S]*f;
      }while(vis[T]);
      }
      return (flow==n*m)?cost:-;
      }
      int main(){
      freopen("C.in","r",stdin);
      freopen("C.out","w",stdout);
      memset(hd,-,sizeof(hd));
      scanf("%d%d",&n,&m);
      for(int i=;i<=n;i++)
      for(int j=;j<=m;j++)
      scanf("%d",&L[i][j]),L[i][j]++;
      for(int i=;i<=n;i++)
      for(int j=;j<=m;j++)
      scanf("%d",&R[i][j]),R[i][j]++;
      S=;T=++cnt;
      for(int i=;i<=n;i++){
      id1[i]=++cnt;
      id2[i]=++cnt;
      }
      build1(rt1,,n);
      build2(rt2,,n);
      for(int i=;i<=n;i++)
      for(int j=;j<=m;j++){
      adde(S,ID(id1[i],j),,);
      adde(ID(id2[i],j),T,,);
      adde(ID(id2[i],j),ID(id2[i],j%m+),inf,);
      adde(ID(id2[i],j),ID(id2[i],(j+m-)%m+),inf,);
      if(R[i][j]<=i)update1(rt1,,n,L[i][j],R[i][j],i,j,*i);
      else if(L[i][j]>=i)update2(rt2,,n,L[i][j],R[i][j],i,j,*(n-i+));
      else update1(rt1,,n,L[i][j],i,i,j,*i),
      update2(rt2,,n,i,R[i][j],i,j,*(n-i+));
      }
      int ans=zkw();
      if(!~ans)puts("no solution");
      else printf("%d\n",ans);
      return ;
      }

      THUSC2017D1T3

【THUSC2017】座位的更多相关文章

  1. THUSC2017 Day1题解

    THUSC2017 Day1题解 巧克力 题目描述 "人生就像一盒巧克力,你永远不知道吃到的下一块是什么味道." 明明收到了一大块巧克力,里面有若干小块,排成n行m列.每一小块都有 ...

  2. THUSC2017题解

    THUSC2017题解 题目都是在LOJ上交的. chocolate LOJ#2977巧克力 这题看着就让人想起了百度之星复赛的\(T5\),就是这题. 因为种类的个数很多,所以把每个种类随意\(ra ...

  3. 团体程序设计天梯赛-练习集L2-010. 排座位

    L2-010. 排座位 时间限制 150 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 布置宴席最微妙的事情,就是给前来参宴的各位宾客安排座位. ...

  4. L2-010. 排座位

    L2-010. 排座位 题目链接:https://www.patest.cn/contests/gplt/L2-010 并查集 相关题目:L2-007. 家庭房产,L3-003. 社交集群 下午打的时 ...

  5. 【THUSC2017】【LOJ2981】如果奇迹有颜色 DP BM 打表 线性递推

    题目大意 有一个 \(n\) 个点的环,你要用 \(m\) 中颜色染这 \(n\) 个点. 要求连续 \(m\) 个点的颜色不能是 $1 \sim m $ 的排列. 两种环相同当且仅当这两个环可以在旋 ...

  6. 【THUSC2017】【LOJ2979】换桌 线段树 网络流

    题目大意 有 \(n\) 个圆形的桌子排成一排,每个桌子有 \(m\) 个座位. 最开始每个位置上都有一个人.现在每个人都要重新选择一个座位,第 \(i\) 桌的第 \(j\) 个人的新座位只能在第 ...

  7. L2-010 排座位 (25 分) (最短路)

    链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805066135879680 题目: 布置宴席最微妙的事情,就是给前 ...

  8. L1-049 天梯赛座位分配​​​​​​​

    L1-049 天梯赛座位分配 (20 分) 天梯赛每年有大量参赛队员,要保证同一所学校的所有队员都不能相邻,分配座位就成为一件比较麻烦的事情.为此我们制定如下策略:假设某赛场有 N 所学校参赛,第 i ...

  9. 航班座位_hihocoder

    题目2 : 航班座位 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi在给一个家庭旅游团订某次航班的机票.该航班的飞机一共有N排座位,每排座位有10个座位,从左到右 ...

随机推荐

  1. AS的使用技巧

    title: AS的使用技巧 date: 2016-04-01 23:34:11 tags: [AndroidStudio] categories: [Tool,IDE] --- 概述 本文记录如何使 ...

  2. [shell] 一次性赋值多个变量

    管道符是fork子进程,子进程的变量无法传回父进程 [root@XM-v106 ~]# echo "1 2 3" | read a b c;echo $a [root@XM-v10 ...

  3. WPF 自定义 MessageBox (相对完善版 v1.0.0.6)

    基于WPF的自定义 MessageBox. 众所周知WPF界面美观.大多数WPF元素都可以简单的修改其样式,从而达到程序的风格统一.可是当你不得不弹出一个消息框通知用户消息时(虽然很不建议在程序中频繁 ...

  4. 【转】git乱码解决方案汇总

    git乱码解决方案汇 2012-11-04更新:官方的“终极”解决方案:msysGit1.7.10开始使用UTF-8编码保存文件名. 2011-10-24更新: 从一篇链接到本篇文章的文章(我对这篇文 ...

  5. python2.6更改为Python2.7

    文中为Python2.6.6,改为Python2.6即可,因为没有/usr/bin/python2.6.6,只有/usr/bin/python2.6 http://blog.csdn.net/jcjc ...

  6. webpack入门指南-step04

    一.建立项目 建一个文件夹,然后新建一个package.json的文件在项目根目录下 如果你使用git管理你的这个项目的话,建议你新建一个.gitignore文件,不要让git提交一些node依赖的模 ...

  7. 【Alpha版本发布】爬虫队长正在待命!

    一.基础功能简介 本团队的爬虫能够从网上搜索相关内容, 并归类,把所爬到的网页或各种类型的文档下载到本地上. 上届团队Beta版本爬虫的主要功能如下: a)可爬取网页,问答页并进行问答文件分类. b) ...

  8. 我是一名IT小小鸟

    我是一只it小小鸟 书中介绍了it界大牛们大学期间的学习方法和对未来的职业规划,相比他们,自我感觉相距甚远,对这学科的热情程度也远远比不上他们. 就拿目前数据结构这门高深的课程,应通过更多的课外扩展来 ...

  9. java中static使用之静态方法注意点

    1.静态方法可以直接调用同类中的静态成员,但是不能直接调用非静态成员,这是为什么呢?大家想一下,静态成员在对象创建之前就要写入内存,所以它在内存中是实实在在的存在的,而非静态还不存在内存中,所以不能调 ...

  10. flex 布局能解决的问题

    flex 布局,可以解决元素在容器中的对齐.方向.顺序,甚至它们是动态的或者不确定大小的新布局模型.Flex容器的主要特征是能够调整其子元素在不同的屏幕大小中能够用最适合的方法填充合适的空间 . 转载 ...