题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1281
棋盘游戏
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2905 Accepted Submission(s):
1702
Problem Description
小希和Gardon在玩一个游戏:对一个N*M的棋盘,在格子里放尽量多的一些国际象棋里面的“车”,并且使得他们不能互相攻击,这当然很简单,但是Gardon限制了只有某些格子才可以放,小希还是很轻松的解决了这个问题(见下图)注意不能放车的地方不影响车的互相攻击。
所以现在Gardon想让小希来解决一个更难的问题,在保证尽量多的“车”的前提下,棋盘里有些格子是可以避开的,也就是说,不在这些格子上放车,也可以保证尽量多的“车”被放下。但是某些格子若不放子,就无法保证放尽量多的“车”,这样的格子被称做重要点。Gardon想让小希算出有多少个这样的重要点,你能解决这个问题么?
Input
输入包含多组数据,
第一行有三个数N、M、K(1<N,M<=100
1<K<=N*M),表示了棋盘的高、宽,以及可以放“车”的格子数目。接下来的K行描述了所有格子的信息:每行两个数X和Y,表示了这个格子在棋盘中的位置。
Output
对输入的每组数据,按照如下格式输出:
Board T have C important blanks
for L chessmen.
Sample Input
3 3 4
1 2
1 3
2 1
2 2
3 3 4
1 2
1 3
2 1
3 2
Sample Output
Board 1 have 0 important blanks for 2 chessmen.
Board 2 have 3 important blanks for 3 chessmen.
Author
Gardon
Source
题目大意:就是车和车之间不能发生攻击.还有一部分位置不可以放置棋子。
解题思路:一行一列只能放一个,那么对于横纵坐标x和y来说一行一列只有一个交点。所以我们就可以根据X坐标与Y坐标把这些点转换为二分图。
对于重要点问题,我们就可以把这个点去掉,涂黑不让他走,然后在进行一次二分匹配,如果发现最大匹配值小了,那么这个就是重要点。
详见代码。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 using namespace std; 6 7 int vis[110],Map[110][110],n,m; 8 int ok[110]; 9 10 bool Find(int x) 11 { 12 for (int i=1; i<=n; i++) 13 { 14 if (Map[x][i]==1&&!vis[i]) 15 { 16 vis[i]=1; 17 if (!ok[i]) 18 { 19 ok[i]=x; 20 return true; 21 } 22 else 23 { 24 if (Find(ok[i])==true) 25 { 26 ok[i]=x; 27 return true; 28 } 29 } 30 } 31 } 32 return false; 33 } 34 35 int main() 36 { 37 int k,x,y,ans,flag=1; 38 while (~scanf("%d%d%d",&n,&m,&k)) 39 { 40 ans=0; 41 memset(Map,0,sizeof(Map)); 42 /* for (int i=1;i<=n;i++) 43 { 44 for (int j=1;j<=m;j++) 45 { 46 Map[i][j]=1; 47 } 48 }*/ 49 memset(ok,0,sizeof(ok)); 50 while (k--) 51 { 52 scanf("%d%d",&x,&y); 53 Map[x][y]=1; 54 } 55 for (int i=1; i<=m; i++) 56 { 57 memset(vis,0,sizeof(vis)); 58 if (Find(i)==true) 59 { 60 ans++; 61 } 62 } 63 int sum=0; 64 for (int i=1; i<=n; i++) 65 { 66 for (int j=1; j<=m; j++) 67 { 68 if (Map[i][j]==1) 69 { 70 memset(ok,0,sizeof(ok)); 71 int kk=0; 72 Map[i][j]=0; 73 for (int k=1; k<=m; k++) 74 { 75 memset(vis,0,sizeof(vis)); 76 if (Find(k)==true) 77 { 78 kk++; 79 } 80 } 81 if (kk<ans) 82 sum++; 83 Map[i][j]=1; 84 } 85 } 86 } 87 printf ("Board %d have %d important blanks for %d chessmen.\n",flag++,sum,ans); 88 } 89 return 0; 90 }