hdu 3360National Treasures

来源:互联网 发布:java sql学生管理系统 编辑:程序博客网 时间:2024/06/04 19:17

这道题向了我好久,看了题解也是一时没想通。

二分图的建模个人感觉挺不容易的,可能是刚学的原因吧~

题意:大厅每个位置都有一个文物或者一个守卫,

             文物是安全的前提是: 关键位置上必须有一个守卫,或者文物本身的位置上有一个守卫。

            求保证每个文物是安全的守卫的最少数量。

分析:由于文物的关键位置在文物的马步或者相邻的位置上,所以此问题可看成二分图。

            以(0,0)位置出发,格子可以分成与(0,0)点距离为奇数的点和偶数的点。

            之后求二分图的最大匹配即可。

#include<stdio.h>#include<string.h>#include<vector>using namespace std;vector<int>map[2550];//建邻接表int r,c,value[55][55],pre[2550];int dir[12][2]={{-1,-2},{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,0},{0,1},{1,0},{0,-1}};int rev[12]={4,5,6,7,0,1,2,3,10,11,8,9};int judge[12]={0x001,0x002,0x004,0x008,0x010,0x020,0x040,0x080,0x100,0x200,0x400,0x800};bool flag[2550];int find(int cur){int i,j;for(i=0;i<map[cur].size();i++){int k=map[cur][i];if(!flag[k]){flag[k]=1;if(!pre[k]||find(pre[k])){pre[k]=cur;return 1;}}}return 0;}void make_map(){int i,j,k;for(i=0;i<r*c;i++)map[i].clear();for(i=0;i<r;i++)for(j=0;j<c;j++){int s=i*c+j;if((i+j)%2==0)continue;if(value[i][j]==-1)continue;for(k=0;k<12;k++){int x=i+dir[k][0];int y=j+dir[k][1];int ss=x*c+y;if(x<0||x>=r||y<0||y>=c)continue;if(value[x][y]==-1)continue;if(judge[k]&value[i][j])  map[s].push_back(ss);        else if(judge[rev[k]]&value[x][y])          map[s].push_back(ss);}}}int main(){int i,j,k=1,a,b;while(scanf("%d%d",&r,&c)!=-1&&(r+c)){memset(pre,0,sizeof(pre));int ans=0;for(i=0;i<r;i++)for(j=0;j<c;j++)        make_map();        int sum=0,s;        for(i=0;i<r;i++)        for(j=0;j<c;j++)        {        if(value[i][j]!=-1&&((i+j)&1))//距离为奇数且没有守卫的点进行匹配        {          memset(flag,0,sizeof(flag));          s=i*c+j;           sum+=find(s);        }        }        printf("%d. %d\n",k++,sum);}return 0;}


原创粉丝点击