题意
一个n*m的格子,然后给出k个石子的坐标,虫子长大于一个格子,且无限伸长知道碰到石头,虫子不能跨过石头睡。求虫子不同睡法的数目。
思路
求大方格内有多少格子数大于1的子方格(矩形)
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=140000+5;
int n;
int m;
int k;
struct Node
{
int x;
int y;
} node[maxn];
bool cmp1(Node a,Node b)
{
if(a.x == b.x)
{
return a.y<b.y;
}
return a.x<b.x;
}
bool cmp2(Node a,Node b)
{
if(a.y==b.y)
{
return a.x<b.x;
}
return a.y<b.y;
}
int main()
{
int T;
int i;
int tx; //(tx,ty)用于记录当前石块的位置
int ty;
int cnt;
scanf("%d",&T);
while(T--)
{
scanf("%d %d %d",&n,&m,&k);
cnt=0;
for(int i=0; i<k; i++)
{
scanf("%d %d",&node[i].x,&node[i].y);
}
if(k==0)
{
if(m>=2) cnt=cnt+m;
if(n>=2) cnt=cnt+n;
printf("%d\n",cnt);
continue;
}
sort(node,node+k,cmp1);
tx=1; //假设初始石块在边界上
ty=0;
cnt=0;
for(i=0; i<k; i++) //扫描每一行,计数横向矩形块的个数
{
if(node[i].x==tx) //case1: 第i块转还在tx行上
{
if(node[i].y-ty>2)
{
cnt=cnt+1;
}
ty=node[i].y;
}
else //case2:第i块砖跳到其他行,
{
if(m+1-ty>2) //case2.1: 判断tx行末尾是否有矩形块
{
cnt=cnt+1;
}
if(m>=2) //case 2.2:若田地宽度大于2,则 跳转的行数 都是 矩形块
{
cnt=cnt+node[i].x-tx-1;
}
if(node[i].y>2) //case 2.3 :判断新的砖块,前面是否有矩形块
{
cnt=cnt+1;
}
tx=node[i].x; //重置行的位置
ty=node[i].y;
}
if(i==k-1) //case3:结束时,后面可能还有很多行的矩形块未计算
{
if(m>=2)
{
cnt=cnt+n-tx;
}
if(m+1-ty>2)
{
cnt=cnt+1;
}
}
}
sort(node,node+k,cmp2);
tx=0;
ty=1;
for(i=0;i<k;i++) //扫描列的矩形块个数 。分析同上
{
if(node[i].y==ty)
{
if(node[i].x-tx>2)
{
cnt++;
}
tx=node[i].x;
}
else
{
if(n+1-tx>2)
{
cnt++;
}
if(n>=2)
{
cnt=cnt+node[i].y-ty-1;
}
if(node[i].x>2)
{
cnt=cnt+1;
}
tx=node[i].x;
ty=node[i].y;
}
if(i==k-1)
{
if(n>=2) cnt=cnt+m-ty;
if(n+1-tx>2) cnt++;
}
}
printf("%d\n",cnt);
}
return 0;
}