先来分析一下这个问题。1.显然天兵的初始位置不重要。2.最坏情况不断使用天兵,2*k次便能解决.
不妨假设不存在天兵:1.我们把调换位置-改为调换兵种(显然成立),那么一个棋子一定调换(否则移到需要的位置调换).2.显然如果我有确定的‘超能力’次数,那么任何一个棋子所能到达的地方有限(bfs)。3.显然我们可以判断1个棋子在超能力步数内必须到达另一个棋子(就是这个棋子,无论怎么调换兵种).问是否是合法方案 那么这就是一个二分图匹配,必须完全匹配。
天兵的意义1.显然一个天兵可以在棋盘上随便走,在每次调换时,找一个棋子把它挪到目的地 这相当于在二分图上任意填‘超能力次数’条边。故先算出最大匹配数,再+超能力数,可以得到最优方案
模型建毕:
#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<cctype>#include<iostream>#include<functional>#include<algorithm>#include<queue>using namespace std;#define MAXN (100+10)#define MAXM (100+10)#define MAXK (100+10)#define MAXT (100+1+10)#define COST (bool(type)^(f[x][y]&1))?(h[x][y]<h[x+path[i][0]][y+path[i][1]]):(h[x][y]>h[x+path[i][0]][y+path[i][1]])const int path[4][2]={{0,1},{1,0},{-1,0},{0,-1}};int n,m,k,t,h[MAXM][MAXN],f[MAXM][MAXN];queue< pair<int,int> > q;bool inside(int x,int y){if (1<=x&&x<=m&&1<=y&&y<=n) {/*cout<<'A'<<x<<' '<<y<<endl;*/ return 1;}else return 0;}void bfs(bool type,int x,int y) //type-> 0 upper 1 lower{memset(f,127,sizeof(f));f[x][y]=0;q.push(make_pair(x,y));while (!q.empty()){pair<int ,int> now=q.front();int &x=now.first,&y=now.second;for (int i=0;i<4;i++){int c=COST;if (inside(x+path[i][0],y+path[i][1]))if (f[x+path[i][0]][y+path[i][1]]>f[x][y]+c){//cout<<(x+path[i][0])<<' '<<(y+path[i][1])<<endl;f[x+path[i][0]][y+path[i][1]]=f[x][y]+c;q.push(make_pair(x+path[i][0],y+path[i][1]));}}q.pop();}}pair<int,int> A[MAXT],B[MAXT];int cost[MAXK][MAXT],a[MAXT];bool b[MAXT];bool find(int x,int maxcost){for (int i=1;i<=2*k+1;i++) if (!b[i]&&cost[x][i]<=maxcost){b[i]=1;if (a[i]==0) {a[i]=x;return 1;}if (find(a[i],maxcost)) {a[i]=x; return 1;}}return 0;}int hopcroft(int maxcost){memset(a,0,sizeof(a));int ans=0;for (int i=1;i<=2*k;i++){memset(b,0,sizeof(b));if (find(i,maxcost)) ans++;}//cout<<ans<<endl;return ans;}int b_search(){int l=0,r=2*k;while (l<r){m=(l+r)>>1;if (hopcroft(m)+m>=2*k) r=m;else l=m+1;}return l;}int main(){//freopen("2547.in","r",stdin);scanf("%d%d%d%d",&m,&n,&k,&t);for (int i=1;i<=2*k+1;i++) scanf("%d%d",&A[i].first,&A[i].second);int size=1;for (int i=1;i<=t;i++){int r;scanf("%d%d%d",&B[size].first,&B[size].second,&r);size++;for (r--;r;r--,size++) B[size]=B[size-1];}for (int i=1;i<=m;i++) for (int j=1;j<=n;j++) scanf("%d",&h[i][j]);/*bfs(1,1,2);for (int i=1;i<=m;i++){for (int j=1;j<=n;j++) cout<<f[i][j]<<' ';cout<<'\n';}*/for (int i=1;i<=2*k;i++){bfs((i>k),A[i].first,A[i].second);for (int j=1;j<=2*k+1;j++){cost[i][j]=f[B[j].first][B[j].second];//cout<<i<<' '<<j<<' '<<cost[i][j]<<endl;}}cout<<b_search()<<endl;return 0;}