ZJU 1654 Place the Robots(二分图)
Given a map consisting of square blocks. There were three kinds of blocks: Wall, Grass, and Empty. His boss wanted to place as many robots as possible in the map. Each robot held a laser weapon which could shoot to four directions (north, east, south, west) simultaneously. A robot had to stay at the block where it was initially placed all the time and to keep firing all the time. The laser beams certainly could pass the grid of Grass, but could not pass the grid of Wall. A robot could only be placed in an Empty block. Surely the boss would not want to see one robot hurting another. In other words, two robots must not be placed in one line (horizontally or vertically) unless there is a Wall between them.
Now that you are such a smart programmer and one of Robert's best friends, He is asking you to help him solving this problem. That is, given the description of a map, compute the maximum number of robots that can be placed in the map.
Input
The first line contains an integer T (<= 11) which is the number of test cases.
For each test case, the first line contains two integers m and n (1<= m, n <=50) which are the row and column sizes of the map. Then m lines follow, each contains n characters of '#', '*', or 'o' which represent Wall, Grass, and Empty, respectively.
Output
For each test case, first output the case number in one line, in the format: "Case :id" where id is the test case number, counting from 1. In the second line just output the maximum number of robots that can be placed in that map.
Sample Input
2
4 4
o***
*###
oo#o
***o
4 4
#ooo
o#oo
oo#o
***#
Sample Output
Case :1
3
Case :2
5
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=654
算法: 不要用搜索来解这道题, 可以灵活运用二分图的想法,构造邻接矩阵。。将横着的没有被阻挡的块合并成一个大块。将竖着的没有被阻挡的块合并成一个大块。 这样得到若干个横向块,和纵向块,如果一横向块与纵向块之间有共同的点,那么就将这两个大块连线(构造一个横向块与纵向块的邻接矩阵)。 构造好之后就可以算横向块与纵向块的最大匹配数。这个数就是机器人的可以摆放的个数。。
代码:
#include <iostream>
using namespace std;
struct XBlock
{
int x;
int starty, endy;
};
struct YBlock
{
int y;
int startx, endx;
};
XBlock bx[2501];
YBlock yb[2501];
char map[51][51];
char temp[51][51];
int casen, n, m, bxn, byn, match;
bool connect[2501][2501];
bool state[1501];
int res[1501];
void copy()
{
int i,j;
for( i = 1; i <= n ; i++)
for( j = 1; j <= m; j++)
temp[i][j] = map[i][j];
}
void MakeXBlock()
{
int i, j, t;
bxn = 0; //记录bx[]的下标
for( i = 1; i <= n ; i++)
for( j = 1; j <= m; j++)
if(temp[i][j] == 'o')
{
bxn ++;
bx[bxn].x = i;
for( t = j; t > 0; t--)//确定横向块的起始坐标
{
if(temp[i][t] == '#')
{
bx[bxn].starty = t+1;
break;
}
else
{
bx[bxn].starty = t;
if(temp[i][t] == 'o' && t != j) //删除这一块中的其他‘o’
temp[i][t] = 'x';
}
}
for( t = j; t <= m; t++ )//确定横向块的结束坐标
{
if(temp[i][t] == '#')
{
bx[bxn].endy = t-1;
break;
}
else
{
bx[bxn].endy = t;
if(temp[i][t] == 'o' && t != j ) //删除这一块中的其他‘o’
temp[i][t] = 'x';
}
}
}
}
void MakeYBlock()
{
int i, j, t;
byn = 0;
for(j = 1; j <= m ;j++)
for(i = 1; i <= n; i++)
if(temp[i][j] == 'o')
{
byn++;
yb[byn].y = j;
for(t = i ; t > 0 ; t--) //确定纵向块的起始坐标
{
if(temp[t][j] == '#')
{
yb[byn].startx = t+1;
break;
}
else
{
yb[byn].startx = t;
if(temp[t][j] == 'o' && t != i) //删除这一块中的其他‘o’
temp[t][j] = 'x';
}
}
for( t = i; t <= n; t++ )//确定纵向快的结束坐标
{
if(temp[t][j] == '#')
{
yb[byn].endx = t-1;
break;
}
else
{
yb[byn].endx = t;
if(temp[t][j] == 'o' && t != i ) //删除这一块中的其他‘o’
temp[t][j] = 'x';
}
}
}
}
bool find(int i) //匈牙利算法,进行最大匹配计算
{
int j;
for(j = 1; j <= byn; j++)
if(connect[i][j] == true && state[j] == false)
{
state[j] = true;
if(res[j] == 0 || find (res[j]) == true)
{
res[j] = i;
return true;
}
}
return false;
}
int main()
{
cin>>casen;
int i, j, num = casen;
while(num--)
{
cin>>n>>m;
for( i = 1; i <= n ; i++)
for( j = 1; j <= m; j++)
cin>>map[i][j];
for( i = 1; i <= 1500; i++) // 初始化结构体里的坐标
{
bx[i].endy = bx[i].starty = bx[i].x = 0;
yb[i].endx = yb[i].startx = yb[i].y = 0;
}
copy();
MakeXBlock();//构造横向块
copy();
MakeYBlock(); //构造纵向块
memset(connect, false, sizeof(connect));
memset(res, 0 , sizeof(res));
for(i = 1; i <= bxn; i++) //构造邻接矩阵
for(j = 1; j <= byn; j++)
{
if((bx[i].x >= yb[j].startx && bx[i].x <= yb[j].endx) &&( yb[j].y >= bx[i].starty && yb[j].y <= bx[i].endy ))
connect[i][j] = true;
}
match = 0;
for(i = 1; i <= bxn; i++) //计算最大匹配数
{
memset(state, false, sizeof(state));
if(find(i))
match++;
}
cout<<"Case :"<<casen- num<<endl;
cout<<match<<endl;
}
return 0;
}
通过数据测试,但本人很遗憾,无法ac,如果有哪位大神能看出其中的差错,或给出一组反例数据(算法绝对没有错,可以网上搜索相关的PPT,这是一道经典题,可惜本人无法将其ac,网上目前还搜索不到相关ac的代码),请告诉我,本人万分感谢!
相关推荐
三相维也纳PFC整流器闭环仿真控制策略研究-中点电位平衡、无功补偿与双载波SVPWM(Simulink仿真实现)
内容概要:本文围绕三相维也纳PFC整流器的闭环仿真控制策略开展深入研究,重点聚焦中点电位平衡控制、无功功率补偿能力以及双载波SVPWM调制技术的集成与优化。通过Simulink平台构建30kW三相维也纳整流器的完整仿真模型,系统性地实现了基于零序电流注入法的中点电位主动平衡控制策略,有效抑制了直流侧中点电压偏移问题;同时设计了高性能的双闭环控制系统,实现了单位功率因数运行与无功功率的灵活动态调节。研究进一步引入双载波SVPWM调制技术(包含马鞍波与羊角波两种形式),提升了系统的电压利用率、调制效率及动态响应性能。全文涵盖了从主电路建模、控制算法设计、调制策略实现到仿真验证的全过程,为高效率、高功率密度的电力电子变换器系统设计提供了完整的理论依据与实践参考。; 适合人群:具备电力电子技术、自动控制理论及仿真建模基础,从事新能源发电、电力系统电能质量治理、工业自动化或电动汽车充电设施等相关领域研究的研发工程师与高校研究生。; 使用场景及目标:①深入掌握三相维也纳PFC整流器的工作机理与系统级控制架构设计;②学习并实现中点电位平衡、无功补偿等关键控制技术;③掌握双载波SVPWM调制策略的原理与仿真实现方法;④应用于新能源并网逆变器、储能变流器、高端电源等对电能质量和变换效率有严苛要求的电力变换系统开发与性能优化。; 阅读建议:建议结合Simulink仿真环境进行实践操作,重点关注控制器参数的整定过程、中点电位波动的抑制效果、无功指令的动态响应特性以及双载波调制波形的生成逻辑与频谱特性,应按照文中所述流程逐步搭建模型并调试,以深入理解各控制模块之间的耦合关系及系统的整体动态行为。
高校科研机构如何通过技术转移实现成果商业化?.docx
科易网基于40亿+科创知识图谱数据库,深度探索AI技术在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,研究科技创新领域的AI+数智化解决方案,推动科技创新与产业创新智能化发展。
技术转移机构如何筛选高潜力合作项目?.docx
技术转移机构如何筛选高潜力合作项目?
政府如何利用科技数据分析提升园区营商环境与产业规划的科学性?.docx
政府如何利用科技数据分析提升园区营商环境与产业规划的科学性?
QYR-23900-2026年全球数字身份智能卡行业总体规模、主要企业国内外市场占有率及排名 Sample-zj.docx
QYR-23900-2026年全球数字身份智能卡行业总体规模、主要企业国内外市场占有率及排名 Sample-zj.docx


