LuoguP3356 火星探险问题(费用流)
題目描述
火星探險隊的登陸艙將在火星表面著陸,登陸艙內有多部障礙物探測車。登陸艙著陸后,探測車將離開登陸艙向先期到達的傳送器方向移動。探測車在移動中還必須采集巖石標本。每一塊巖石標本由最先遇到它的探測車完成采集。每塊巖石標本只能被采集一次。巖石標本被采集后,其他探測車可以從原來巖石標本所在處通過。探測車不能通過有障礙的地面。本題限定探測車只能從登陸處沿著向南或向東的方向朝傳送器移動,而且多個探測車可以在同一時間占據同一位置。如果某個探測車在到達傳送器以前不能繼續前進,則該車所采集的巖石標本將全部損失。
用一個 P·Q 網格表示登陸艙與傳送器之間的位置。登陸艙的位置在(X1,Y1)處,傳送器
的位置在(XP ,YQ)處。
X 1,Y 1 X 2 , Y 1 X 3 , Y 1 ... X P-1, Y 1 X P , Y 1
X 1,Y 2 X 2 , Y 2 X 3 , Y 2 ... X P-1, Y 2 X P , Y 2
X 1, Y 3 X 2 , Y 3 X 3 ,Y 3 ... X P-1, Y 3 X P , Y 3
... ...
X 1 ,Y Q-1 X 2 , Y Q-1 X 3 , Y Q-1 ... X P-1, Y Q-1 X P , Y Q-1
X 1,Y Q X 2 , Y Q X 3 , Y Q ... X P-1, Y Q X P ,Y Q
給定每個位置的狀態,計算探測車的最優移動方案,使到達傳送器的探測車的數量最多,
而且探測車采集到的巖石標本的數量最多
輸入輸出格式
輸入格式:
第 1行為探測車數,第 2 行為 P 的值,第3 行為Q 的值。接下來的 Q 行是表示登陸艙與傳送器之間的位置狀態的 P·Q 網格。用 3 個數字表示火星表面位置的狀態:0 表示平坦無障礙,1表示障礙,2 表示石塊。
輸出格式:
每行包含探測車號和一個移動方向,0 表示向南移動,1 表示向東移動。
解題思路:
拆點套路。
代碼:
1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 typedef long long lnt; 6 const int oo=0x3f3f3f3f; 7 struct pnt{ 8 int hd; 9 int lst; 10 int pre; 11 int dis; 12 int val; 13 bool vis; 14 }p[100000]; 15 struct ent{ 16 int twd; 17 int lst; 18 int vls; 19 int dis; 20 int his; 21 }e[100000]; 22 struct int_2{ 23 int i,j; 24 }pi[100000]; 25 int cnt; 26 int n,m; 27 int s,t; 28 int num; 29 int mp[101][101]; 30 int no[101][101][2]; 31 std::queue<int>Q; 32 void ade(int f,int t,int v,int d) 33 { 34 cnt++; 35 e[cnt].his=v; 36 e[cnt].twd=t; 37 e[cnt].vls=v; 38 e[cnt].dis=d; 39 e[cnt].lst=p[f].hd; 40 p[f].hd=cnt; 41 return ; 42 } 43 bool Spfa(void) 44 { 45 while(!Q.empty()) 46 Q.pop(); 47 for(int i=1;i<=t;i++) 48 { 49 p[i].dis=p[i].val=oo; 50 p[i].vis=false; 51 } 52 p[t].pre=-1; 53 p[s].vis=true; 54 p[s].dis=0; 55 Q.push(s); 56 while(!Q.empty()) 57 { 58 int x=Q.front(); 59 Q.pop(); 60 p[x].vis=false; 61 for(int i=p[x].hd;i;i=e[i].lst) 62 { 63 int to=e[i].twd; 64 if(p[to].dis>p[x].dis+e[i].dis&&e[i].vls>0) 65 { 66 p[to].dis=p[x].dis+e[i].dis; 67 p[to].val=std::min(p[x].val,e[i].vls); 68 p[to].pre=x; 69 p[to].lst=i; 70 if(p[to].vis) 71 continue; 72 p[to].vis=true; 73 Q.push(to); 74 } 75 } 76 } 77 return p[t].pre!=-1; 78 } 79 int Ek(void) 80 { 81 int ans=0; 82 while(Spfa()) 83 { 84 ans+=p[t].val; 85 for(int i=t;i!=s;i=p[i].pre) 86 { 87 e[p[i].lst].vls-=p[t].val; 88 e[((p[i].lst-1)^1)+1].vls+=p[t].val; 89 } 90 } 91 return ans; 92 } 93 void Dfs(int ii,int jj,int Ntt) 94 { 95 int w=no[ii][jj][1]; 96 int x=no[ii][jj][0]; 97 int y=no[ii][jj+1][0]; 98 int z=no[ii+1][jj][0]; 99 for(int i=p[w].hd;i;i=e[i].lst) 100 { 101 if(e[i].vls>=e[i].his) 102 continue; 103 e[i].vls++; 104 int to=e[i].twd; 105 if(to==y) 106 { 107 printf("%d %d\n",Ntt,1); 108 Dfs(ii,jj+1,Ntt); 109 return ; 110 }else if(to==z) 111 { 112 printf("%d %d\n",Ntt,0); 113 Dfs(ii+1,jj,Ntt); 114 return ; 115 } 116 } 117 return ; 118 } 119 int main() 120 { 121 // freopen("a.in","r",stdin); 122 scanf("%d%d%d",&num,&m,&n); 123 for(int i=1;i<=n;i++) 124 { 125 for(int j=1;j<=m;j++) 126 { 127 no[i][j][0]=++cnt; 128 pi[cnt]=(int_2){i,j}; 129 } 130 } 131 for(int i=1;i<=n;i++) 132 { 133 for(int j=1;j<=m;j++) 134 { 135 no[i][j][1]=++cnt; 136 pi[cnt]=(int_2){i,j}; 137 } 138 } 139 s=cnt+1; 140 t=cnt+2; 141 cnt=0; 142 for(int i=1;i<=n;i++) 143 { 144 for(int j=1;j<=m;j++) 145 { 146 scanf("%d",&mp[i][j]); 147 if(mp[i][j]==1) 148 continue; 149 if(mp[i][j]==2) 150 { 151 ade(no[i][j][0],no[i][j][1],1,-1); 152 ade(no[i][j][1],no[i][j][0],0,1); 153 } 154 ade(no[i][j][0],no[i][j][1],oo,0); 155 ade(no[i][j][1],no[i][j][0],0,0); 156 } 157 } 158 159 for(int i=1;i<=n;i++) 160 { 161 for(int j=1;j<=m;j++) 162 { 163 if(mp[i][j]==1) 164 continue; 165 if(i+1<=n&&mp[i+1][j]!=1) 166 { 167 ade(no[i][j][1],no[i+1][j][0],oo,0); 168 ade(no[i+1][j][0],no[i][j][1],0,0); 169 } 170 if(j+1<=m&&mp[i][j+1]!=1) 171 { 172 ade(no[i][j][1],no[i][j+1][0],oo,0); 173 ade(no[i][j+1][0],no[i][j][1],0,0); 174 } 175 } 176 } 177 ade(s,no[1][1][0],num,0); 178 ade(no[1][1][0],s,0,0); 179 ade(no[n][m][1],t,num,0); 180 ade(t,no[n][m][1],0,0); 181 num=Ek(); 182 for(int i=1;i<=num;i++) 183 Dfs(1,1,i); 184 return 0; 185 }轉載于:https://www.cnblogs.com/blog-Dr-J/p/10210863.html
總結
以上是生活随笔為你收集整理的LuoguP3356 火星探险问题(费用流)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 下载整个网站的软件
- 下一篇: 20十年后的计算机作文600字,二十年后