Poj 3041 Asteroids + Poj 2226 Muddy Fields(二分图与一类选方格题目)

秒速五厘米 2021-11-22 21:01 394阅读 0赞

Poj 3041 Asteroids

思路:把方阵看做一个特殊的二分图(以行列分别作为两个顶点集V1、V2,其中| V1|=| V2|)
然后把每行x或者每列y看成一个点,而障碍物(x,y)可以看做连接x和y的边。按照这种思路构图后。问题就转化成为选择最少的一些点(x或y),使得从这些点与所有的边相邻,其实这就是最小点覆盖问题。.

  1. #include <cstdio>
  2. #include <cstring>
  3. const int N=505;
  4. bool map[N][N];
  5. bool vis[N];
  6. int match[N];
  7. int n,k;
  8. bool Dfs (int u)
  9. {
  10. for (int v=1;v<=n;v++)
  11. if (vis[v] == false && map[u][v])
  12. {
  13. vis[v]=true;
  14. if (match[v]==0 || Dfs(match[v]))
  15. {
  16. match[v]=u;
  17. return true;
  18. }
  19. }
  20. return false;
  21. }
  22. int main ()
  23. {
  24. int i,temp1,temp2,sum;
  25. scanf("%d%d",&n,&k);
  26. memset(map,false,sizeof(map));
  27. memset(match,0,sizeof(match));
  28. for (i=1;i<=k;i++)
  29. {
  30. scanf("%d%d",&temp1,&temp2);
  31. map[temp1][temp2]=true;
  32. }
  33. for (sum=0,i=1;i<=n;i++)
  34. {
  35. memset(vis,false,sizeof(vis));
  36. if (Dfs(i))
  37. sum++;
  38. }
  39. printf("%d\n",sum);
  40. return 0;
  41. }

Poj 2226 Muddy Fields

题意:给定一个矩阵,其中有一些地方有水,用一些长度任意,宽度为1长度不限的木板盖住这些有水的地方,问至少需要几块板子。
思路:二分图最小点集覆盖。
二分图建图方法如下:横行的连续*作为X集合里的顶点,纵行的连续*作为Y集合的顶点。
若X和Y集合中的顶点在原图中有相交,则这两个顶点连一条边。

  1. #include <cstdio>
  2. #include <cstring>
  3. const int N=1000;
  4. char graph[55][55];
  5. bool map[N][N];
  6. bool vis[N];
  7. int match[N],a[N][N],b[N][N];
  8. int R,C,x=1,y=1;
  9. bool DFS (int u)
  10. {
  11. for (int v=1;v<=y;v++)
  12. if (vis[v] == false && map[u][v])
  13. {
  14. vis[v]=true;
  15. if (match[v]==0 || DFS(match[v]))
  16. {
  17. match[v]=u;
  18. return true;
  19. }
  20. }
  21. return false;
  22. }
  23. int main ()
  24. {
  25. int i,j,ans=0;
  26. scanf("%d%d",&R,&C);
  27. for (i=1;i<=R;i++)
  28. scanf("%s",graph[i]+1);
  29. memset(a,0,sizeof(a));
  30. memset(b,0,sizeof(b));
  31. memset(map,false,sizeof(map));
  32. memset(match,0,sizeof(match));
  33. for (i=1;i<=R;i++) //扫连续横
  34. for (j=1;j<=C;j++)
  35. if (graph[i][j]=='*')
  36. {
  37. a[i][j]=x;
  38. x+=(graph[i][j+1]!='*');
  39. }
  40. for (i=1;i<=C;i++) //扫连续纵
  41. for (j=1;j<=R;j++)
  42. if (graph[j][i]=='*') //注意横纵坐标
  43. {
  44. b[j][i]=y;
  45. y+=(graph[j+1][i]!='*');
  46. }
  47. for (i=1;i<=R;i++)
  48. for (j=1;j<=C;j++)
  49. if (graph[i][j] == '*')
  50. map[a[i][j]][b[i][j]]=true;
  51. for (i=1;i<=x;i++)
  52. {
  53. memset(vis,false,sizeof(vis));
  54. if (DFS(i))
  55. ans++;
  56. }
  57. printf("%d\n",ans);
  58. return 0;
  59. }

发表评论

表情:
评论列表 (有 0 条评论,394人围观)

还没有评论,来说两句吧...

相关阅读