CodeForces 382D Ksenia and Pawns

来源:互联网 发布:微盘软件开发 编辑:程序博客网 时间:2024/05/18 00:50

题意:

有一副棋盘  每个格子上有方向  要求在棋盘上放两个人  两个人按照方向同时走  得分为两人步数之和

规定除了停止格子‘#’以外每个格子只能容下一个人  求最大的得分  如果得分无穷大则输出-1


思路:

1.很容易想到  一旦把人放在棋盘上  他的路线就固定了

2.如果棋盘上的路线有一个环  那么至少可以让一个人在环里不停走  即有环则输出-1

3.棋盘上没有环则有正常的答案  因此我们需要找出所有的可能的路径  然后尽量选择长的路径放小人

   但是如果只看长度那么两个人的路径就可能冲突(即在带方向的格子里相撞)  解决这个问题是本题关键

   假设route[0]~route[n]为路径长度从大到小排序

   如果route[1]<route[0]  这时根本不需要冒险尝试route[1]  我只需要让第二个人跟在第一个人后面都走route[0]就一定最优(ans = route[0]*2-1)

   如果route[1/2/……]==route[0]  我们已经有了一个保险的答案就是route[0]*2-1  这时只要看能不能找到更长的就行了  显而易见如果有更长的只能是route[0]*2  那么就可以判断多条和route[0]等长的路径是否与route[0]冲突  只要不冲突就可以了


#include<cstdio>#include<cstring>#include<algorithm>#include<map>using namespace std;#define M 2005int n,m,cir,top,stp;char maz[M][M];int vis[M][M];struct route{int sx,sy,num;bool operator<(const route fa) const{return num>fa.num;}}sol[M*M];void dfs(int x,int y,int sx,int sy){char tmp=maz[x][y];int mx,my;vis[x][y]=1;if(tmp=='@') cir=1;else if(tmp=='#'){sol[top].sx=sx;  sol[top].sy=sy;  sol[top].num=stp;top++;}else{stp++;if(tmp=='^') mx=-1,my=0;else if(tmp=='<') mx=0,my=-1;else if(tmp=='>') mx=0,my=1;else if(tmp=='v') mx=1,my=0;maz[x][y]='@';dfs(x+mx,y+my,sx,sy);maz[x][y]=tmp;stp--;}}void run(int x,int y,int f){char tmp=maz[x][y];int mx,my;if(tmp=='#') return ;vis[x][y]=f;if(tmp=='^') mx=-1,my=0;else if(tmp=='<') mx=0,my=-1;else if(tmp=='>') mx=0,my=1;else if(tmp=='v') mx=1,my=0;run(x+mx,y+my,f+1);}bool check(int x,int y,int f){char tmp=maz[x][y];int mx,my,tmpf=vis[x][y];if(tmpf==f) return true;if(tmp=='#') return false;vis[x][y]=f;if(tmp=='^') mx=-1,my=0;else if(tmp=='<') mx=0,my=-1;else if(tmp=='>') mx=0,my=1;else if(tmp=='v') mx=1,my=0;if(check(x+mx,y+my,f+1)){vis[x][y]=tmpf;return true;}return false;}int main(){int i,j;scanf("%d%d",&n,&m);for(i=1;i<=n;i++) scanf("%s",maz[i]+1);memset(vis,0,sizeof(vis));for(i=1;i<=n;i++){for(j=1;j<=m;j++){if(vis[i][j]) continue;stp=0;dfs(i,j,i,j);if(cir){printf("-1\n");return 0;}}}sort(sol,sol+top);memset(vis,-1,sizeof(vis));run(sol[0].sx,sol[0].sy,0);for(i=0;i<top;i++){if(sol[i].num!=sol[0].num) break;if(!check(sol[i].sx,sol[i].sy,0)){printf("%d\n",sol[0].num*2);return 0;}}printf("%d\n",sol[0].num*2-1);return 0;} 


0 0
原创粉丝点击