1. 程式人生 > >bzoj2547: [Ctsc2002]玩具兵

bzoj2547: [Ctsc2002]玩具兵

cstring family cst 結果 cto typedef ems read cts

劃了一天水,其實我還是有點愧疚的。

傳送門

其實是水題,然而我真是太蠢了。。。

首先不考慮天兵,其他兵要到一個點去一定是通過它-另一種兵-它……這樣多次交換的,並且交換對象是無所謂的,和它換的兵最終會是在原位置。

而且騎兵和步兵的數量相等,就不存在一個兵找不到人跟它換的情況,那麽一個確定的方案下換的次數最多的兵換的次數就是答案。

先spfa找出每個兵到每個位置的最小換的次數,然後二分答案,把每個兵向它可以到的地方連邊,跑最大匹配,考慮到還有天兵,而天兵是可以一步登天的超神存在,所以如果最大匹配數+現在check的ans>=總兵數即OK。

因為一直在劃水,斷斷續續地寫這個代碼 ,又困得要命,仿佛活在夢中,結果竟然1A了,神奇。

技術分享圖片
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
const int N=107; 
typedef long long LL;
using namespace std;
int n,m,k,t,R[N],h[N][N],dis[N][N],dp[N][N][2
],vis[N][N][2]; int dx[5]={0,0,1,-1},dy[5]={1,-1,0,0}; template<typename T>void read(T &x) { char ch=getchar(); x=0; T f=1; while(ch!=-&&(ch<0||ch>9)) ch=getchar(); if(ch==-) f=-1,ch=getchar(); for(;ch>=0&&ch<=9;ch=getchar()) x=x*10+ch-0; x*=f; }
struct node { int x,y,o; node(){} node(int x,int y,int o):x(x),y(y),o(o){} }b[N],p[N]; queue<node>que; void spfa(int sx,int sy,int k) { memset(dp,127,sizeof(dp)); if(k) dp[sx][sy][0]=0,que.push(node(sx,sy,0)); else dp[sx][sy][1]=0,que.push(node(sx,sy,1)); while(!que.empty()) { node now=que.front(); que.pop(); int x=now.x,y=now.y,o=now.o; vis[x][y][o]=0; for(int i=0;i<4;i++) { int xx=now.x+dx[i],yy=now.y+dy[i],oo,t; if(xx>=1&&xx<=n&&yy>=1&&yy<=m) { if((o==0&&h[xx][yy]>=h[x][y])||(o==1&&h[xx][yy]<=h[x][y])) t=dp[x][y][o],oo=o; else t=dp[x][y][o]+1,oo=o^1; if(dp[xx][yy][oo]>t) { dp[xx][yy][oo]=t; if(!vis[xx][yy][oo]) { que.push(node(xx,yy,oo)); vis[xx][yy][oo]=1; } } } } } } int ok[N][N],vs[N],pr[N],sum[N]; int find(int x) { for(int i=1;i<=2*k;i++) if(ok[x][i]&&!vs[i]) { vs[i]=1; if(!pr[i]||find(pr[i])) { pr[i]=x; return 1; } } return 0; } int ck(int ans) { int res=0; for(int i=1;i<=2*k;i++) for(int j=1;j<=t;j++) { if(dis[i][j]<=ans) for(int kk=1;kk<=R[j];kk++) ok[i][sum[j-1]+kk]=1; else for(int kk=1;kk<=R[j];kk++) ok[i][sum[j-1]+kk]=0; } memset(pr,0,sizeof(pr)); for(int i=1;i<=2*k;i++) { memset(vs,0,sizeof(vs)); if(find(i)) res++; } if(res+ans>=2*k) return 1; else return 0; } int main() { read(n); read(m); read(k); read(t); for(int i=1;i<=2*k+1;i++) { read(b[i].x); read(b[i].y); } for(int i=1;i<=t;i++) { read(p[i].x); read(p[i].y); read(R[i]); sum[i]=sum[i-1]+R[i]; } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) read(h[i][j]); memset(dis,127,sizeof(dis)); for(int i=1;i<=2*k;i++) { spfa(b[i].x,b[i].y,(i<=k)); for(int j=1;j<=t;j++) dis[i][j]=min(dp[p[j].x][p[j].y][0],dp[p[j].x][p[j].y][1]); } if(ck(0)) { puts("0"); return 0; } int l=1,r=1e9,ans=r; while(l<=r) { int mid=((l+r)>>1); if(ck(mid)) ans=mid,r=mid-1; else l=mid+1; } printf("%d\n",ans); return 0; } /* 4 6 2 5 1 1 1 5 4 1 4 5 3 3 1 2 1 2 6 1 3 2 1 3 6 1 4 3 1 3 2 6 1 3 5 2 1 7 4 4 6 2 3 1 4 3 4 4 3 4 3 2 3 */
View Code

bzoj2547: [Ctsc2002]玩具兵