• 【THUSC2017】座位


    题目背景

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

    题目描述

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

    移动座位过程分为两步:

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

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

    详情如下图:

    img

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

    输入格式

    从标准输入读入数据。

    第一行输入两个数 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)$
      •   1 #include<bits/stdc++.h>
          2 #define inf 0x3f3f3f3f
          3 using namespace std;
          4 const int N=1000010,K=310;
          5 int S,T,n,m,o,hd[N],dis[N],vis[N],sum1[K],sum2[K];
          6 int id1[K][K],id2[K][K],id3[K][K],id4[K][K],L[K][K],R[K][K];
          7 struct Edge{int v,nt,f,w;}E[N<<1];
          8 void adde(int u,int v,int f,int w){
          9     E[o]=(Edge){v,hd[u],f,w};hd[u]=o++;
         10     E[o]=(Edge){u,hd[v],0,-w};hd[v]=o++; 
         11 }
         12 queue<int>q;
         13 bool bfs(){
         14     memset(vis,0,sizeof(vis));
         15     memset(dis,0x3f,sizeof(dis));
         16     q.push(T);dis[T]=0;vis[T]=1;
         17     while(!q.empty()){
         18         int u=q.front();q.pop();
         19         vis[u]=0;
         20         for(int i=hd[u];~i;i=E[i].nt)if(E[i^1].f){
         21             int v=E[i].v;
         22             if(dis[v]>dis[u]+E[i^1].w){
         23                 dis[v]=dis[u]+E[i^1].w;
         24                 if(!vis[v])vis[v]=1,q.push(v);
         25             } 
         26         }
         27     }
         28     return dis[S]!=inf;
         29 }
         30 int dfs(int u,int F){
         31     vis[u]=1;
         32     if(u==T||!F)return F;
         33     int flow=0,f;
         34     for(int i=hd[u];~i;i=E[i].nt){
         35         int v=E[i].v;
         36         if(!vis[v]&&dis[v]+E[i].w==dis[u]&&E[i].f&&(f=dfs(v,min(F,E[i].f)))){
         37             flow+=f;F-=f;
         38             E[i].f-=f,E[i^1].f+=f;
         39             if(!F)break;
         40         }
         41     }
         42     return flow;
         43 }
         44 int zkw(){
         45     int flow=0,cost=0,f;
         46     while(bfs()){
         47         do{
         48             memset(vis,0,sizeof(vis));
         49             f=dfs(S,inf);
         50             flow+=f;
         51             cost+=dis[S]*f;
         52         }while(vis[T]);
         53     }
         54     return flow==n*m?cost:-1;
         55 }
         56 int main(){
         57 //    freopen("C.in","r",stdin);
         58 //    freopen("C.out","w",stdout);
         59     memset(hd,-1,sizeof(hd));
         60     scanf("%d%d",&n,&m);
         61     for(int i=1;i<=n;i++)
         62     for(int j=1;j<=m;j++){
         63         id1[i][j]=(i-1)*m+j;
         64         id2[i][j]=n*m+id1[i][j];
         65         id3[i][j]=n*m+id2[i][j];
         66         id4[i][j]=n*m+id3[i][j];
         67     }
         68     S=0,T=id4[n][m]+1;
         69     for(int i=1;i<=n;i++){
         70     for(int j=1;j<=m;j++){
         71             adde(S,id1[i][j],1,0);
         72             adde(id2[i][j],id4[i][j],1,0);
         73             adde(id3[i][j],id4[i][j],1,0);
         74             adde(id4[i][j],T,1,0);
         75             int ri=j%m+1,le=(j+m-2)%m+1;
         76             adde(id2[i][j],id2[i][ri],inf,1);
         77             adde(id2[i][j],id2[i][le],inf,1);
         78             adde(id3[i][j],id3[i][ri],inf,1);
         79             adde(id3[i][j],id3[i][le],inf,1);
         80             if(i>1)adde(id2[i][j],id2[i-1][j],inf,2);
         81             if(i<n)adde(id3[i][j],id3[i+1][j],inf,2);
         82         }
         83     }
         84     for(int i=1;i<=n;i++)
         85     for(int j=1;j<=m;j++){scanf("%d",&L[i][j]);sum2[++L[i][j]]++;}
         86     for(int i=1;i<=n;i++)
         87     for(int j=1;j<=m;j++){scanf("%d",&R[i][j]);sum1[++R[i][j]]++;}
         88     for(int i=1;i<=n;i++){
         89         sum1[i]+=sum1[i-1];
         90         if(sum1[i]>i*m)return puts("no solution"),0;
         91     }
         92     for(int i=n;i>=1;i--){
         93         sum2[i]+=sum2[i+1];
         94         if(sum2[i]>(n-i+1)*m)return puts("no solution"),0;
         95     }
         96     for(int i=1;i<=n;i++)
         97     for(int j=1;j<=m;j++){
         98         if(L[i][j]<=i&&i<=R[i][j])adde(id1[i][j],id2[i][j],1,0),adde(id1[i][j],id3[i][j],1,0);
         99         else if(i<L[i][j])adde(id1[i][j],id3[L[i][j]][j],1,(L[i][j]-i)<<1);
        100         else adde(id1[i][j],id2[R[i][j]][j],1,(i-R[i][j])<<1);
        101     }
        102     int ans = zkw();
        103     if(!~ans)puts("-1");
        104     else printf("%d
        ",ans);
        105     return 0;
        106 } 
        70pts
      •   1 #include<bits/stdc++.h>
          2 #define inf 0x3f3f3f3f
          3 #define il inline 
          4 #define ID(i,j) (i-1)*m+j
          5 using namespace std;
          6 const int N=100010,M=100010;
          7 int n,m,L[301][11],R[301][11],ls1[1801],rs1[1801],ls2[1801],rs2[1801],cnt,rt1,rt2;
          8 int S,T,o,hd[N],vis[N],dis[N],id1[301],id2[301],q[N],head,tail;
          9 struct Edge{int v,nt,f,w;}E[M<<1];
         10 il void adde(int u,int v,int f,int w){
         11 //    printf("%d %d %d %d
        ",u,v,f,w);
         12     E[o]=(Edge){v,hd[u],f,w};hd[u]=o++;
         13     E[o]=(Edge){u,hd[v],0,-w};hd[v]=o++;
         14 }
         15 il void Adde(int u,int v,int f,int w){
         16     for(int i=1;i<=m;i++)adde(ID(u,i),ID(v,i),f,w);
         17 }
         18 void build1(int&k,int l,int r){
         19     k=++cnt;
         20     if(l==r){Adde(k,id2[l],inf,-2*l);return;}
         21     int mid=(l+r)>>1;
         22     build1(ls1[k],l,mid);
         23     build1(rs1[k],mid+1,r);
         24     Adde(k,ls1[k],inf,0);
         25     Adde(k,rs1[k],inf,0);
         26 }
         27 void build2(int&k,int l,int r){
         28     k=++cnt;
         29     if(l==r){Adde(k,id2[l],inf,-2*(n-l+1));return;}
         30     int mid=(l+r)>>1;
         31     build2(ls2[k],l,mid);
         32     build2(rs2[k],mid+1,r);
         33     Adde(k,ls2[k],inf,0);
         34     Adde(k,rs2[k],inf,0);
         35 }
         36 void update1(int k,int l,int r,int x,int y,int i,int j,int val){
         37     if(l==x&&r==y){adde(ID(id1[i],j),ID(k,j),inf,val);}
         38     else{
         39         int mid=(l+r)>>1;
         40         if(y<=mid)update1(ls1[k],l,mid,x,y,i,j,val);
         41         else if(x>mid)update1(rs1[k],mid+1,r,x,y,i,j,val);
         42         else update1(ls1[k],l,mid,x,mid,i,j,val),update1(rs1[k],mid+1,r,mid+1,y,i,j,val);
         43     }
         44 }
         45 void update2(int k,int l,int r,int x,int y,int i,int j,int val){
         46     if(l==x&&r==y){adde(ID(id1[i],j),ID(k,j),inf,val);}
         47     else{
         48         int mid=(l+r)>>1;
         49         if(y<=mid)update2(ls2[k],l,mid,x,y,i,j,val);
         50         else if(x>mid)update2(rs2[k],mid+1,r,x,y,i,j,val);
         51         else update2(ls2[k],l,mid,x,mid,i,j,val),update2(rs2[k],mid+1,r,mid+1,y,i,j,val);
         52     }
         53 }
         54 bool spfa(){
         55     for(int i=0;i<=cnt*m;i++)vis[i]=0,dis[i]=inf;
         56     head=tail=0;dis[q[tail++]=T]=0;
         57     while(head!=tail){
         58         int u=q[head++];if(head==N)head=0;
         59         vis[u]=0;
         60         for(int i=hd[u];~i;i=E[i].nt)if(E[i^1].f){
         61             int v=E[i].v;
         62             if(dis[v]>dis[u]+E[i^1].w){
         63                 dis[v]=dis[u]+E[i^1].w;
         64                 if(!vis[v]){
         65                     vis[v]=1,q[tail++]=v;
         66                     if(tail==N)tail=0;
         67                 }
         68             }
         69         }
         70     }
         71     return dis[S]!=inf;
         72 }
         73 int dfs(int u,int F){
         74     vis[u]=1;
         75     if(u==T||!F)return F;
         76     int flow=0,f;
         77     for(int i=hd[u];~i;i=E[i].nt){
         78         int v=E[i].v;
         79         if(E[i].f&&!vis[v]&&dis[v]+E[i].w==dis[u]&&(f=dfs(v,min(F,E[i].f)))){
         80             flow+=f,F-=f;
         81             E[i].f-=f,E[i^1].f+=f;
         82             if(!F)break;
         83         }
         84     }
         85     return flow;
         86 }
         87 int zkw(){
         88     int flow=0,cost=0,f;
         89     while(spfa()){
         90         do{
         91             for(int i=0;i<=cnt*m;i++)vis[i]=0;
         92             f=dfs(S,inf);
         93             flow+=f;
         94             cost+=dis[S]*f;
         95         }while(vis[T]);
         96     }
         97     return (flow==n*m)?cost:-1;
         98 }
         99 int main(){
        100     freopen("C.in","r",stdin);
        101     freopen("C.out","w",stdout);
        102     memset(hd,-1,sizeof(hd));
        103     scanf("%d%d",&n,&m);
        104     for(int i=1;i<=n;i++)
        105     for(int j=1;j<=m;j++)
        106     scanf("%d",&L[i][j]),L[i][j]++;
        107     for(int i=1;i<=n;i++)
        108     for(int j=1;j<=m;j++)
        109     scanf("%d",&R[i][j]),R[i][j]++;
        110     S=0;T=++cnt;
        111     for(int i=1;i<=n;i++){
        112         id1[i]=++cnt;
        113         id2[i]=++cnt;
        114     }
        115     build1(rt1,1,n);
        116     build2(rt2,1,n);
        117     for(int i=1;i<=n;i++)
        118     for(int j=1;j<=m;j++){
        119         adde(S,ID(id1[i],j),1,0);
        120         adde(ID(id2[i],j),T,1,0);
        121         adde(ID(id2[i],j),ID(id2[i],j%m+1),inf,1);
        122         adde(ID(id2[i],j),ID(id2[i],(j+m-2)%m+1),inf,1); 
        123         if(R[i][j]<=i)update1(rt1,1,n,L[i][j],R[i][j],i,j,2*i);
        124         else if(L[i][j]>=i)update2(rt2,1,n,L[i][j],R[i][j],i,j,2*(n-i+1));
        125         else update1(rt1,1,n,L[i][j],i,i,j,2*i),
        126              update2(rt2,1,n,i,R[i][j],i,j,2*(n-i+1));
        127     }
        128     int ans=zkw();
        129     if(!~ans)puts("no solution");
        130     else printf("%d
        ",ans);
        131     return 0;
        132 }
        THUSC2017D1T3
  • 相关阅读:
    c++ 图解快速排序算法
    Shell脚本检测文件夹是否已被挂载的方法
    Linux使用mount挂载samba共享
    PHP使用字符串名称调用类的方法
    命令行查看端口号被进程占用
    Golang Clearing slice
    送给自己的程序员箴言
    Entity Framework6 with Visual Studio 2013 update3 for Oracle 11g
    深入浅出ASP.NET MVC5系列之一
    年终福利:调试.NET Framework源代码
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/10246748.html
Copyright © 2020-2023  润新知