ACM:The Happy Worm (C++ 实现)

探讨在一个由石头和空地组成的矩形区域内,一只快乐蠕虫如何在睡眠时尽可能地伸展身躯而不触碰石头,同时保持至少两格长度。通过分析石头分布,计算蠕虫的不同睡眠位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

The Happy Worm
Time Limit: 1.0 Seconds   Memory Limit:65536K

The Happy Worm lives in an m*n rectangular field. There are k stones placed in certain locations of the field. (Each square of the field is either empty, or contains a stone.) Whenever the worm sleeps, it lies either horizontally or vertically, and stretches so that its length increases as much as possible. The worm will not go in a square with a stone or out of the field. The happy worm can not be shorter than 2 squares.

The question you are to answer is how many different positions this worm could be in while sleeping.

Input

The first line of the input file contains a single integer t (1 ≤ t ≤ 11), the number of test cases, followed by the input data for each test case. The first line of each test case contains three integersm, n, andk (1 ≤ m,n ≤ 10000, 0 ≤ k ≤ 200000). The input for this test case will be followed byk lines. Each line contains two integers which specify the row and column of a stone. No stone will be given twice.

Output

There should be one line per test case containing the number of positions the happy worm can be in.

Sample Input

1
5 5 6
1 5
2 3
2 4
4 2 
4 3
5 1

Sample Output

9

题意解析:
        题目意思是有一个M*N的矩阵,里边有一些石头,然后有一只小虫在矩阵里睡觉,睡觉的时候小虫的身躯需要尽可能的全部伸展(横向或者纵向睡,并全部占据此方向的所有空格,直到遇到石头),同时它至少占两个格才能睡得下,最后问这只虫有多少种不同睡法?

解法:
       本题个人想到两种方向的解法,一种是常规算法,按照题目定义一个矩阵,将石头的位置标记出来,然后逐行逐列的算可行位置。另一只是差位计算,将所有石头的位置录入数组中,然后将同一行(同一列)的依次提取出来,放入新的数组,然后对其按从小到大排序,相邻两位间相减,算出每一行(每一列)的可行位置数量,再相加的到结果。第二种方法还要注意在矩阵中某一行或者某一列没有一个石头的情况,不要漏算了。

       两种方法技术实现上相差不大,下边附上第一种方法(环境是VS2012),第二种方法需要的请自行实现了。

#include<iostream>

using namespace std;


int main(){
	int n,ro,co,st,a,b,pr,pc,text,num;
	cin>>n;
	while(n>0){
		--n;
		num=0;
		cin>>ro>>co>>st;
		int **f = new int*[ro];	//分配一位数组
		for(a=0; a<ro; a++){   //分配二维数组
				f[a] = new int[co];
		}
		for(a=0; a<ro; a++){   //数组初始化
			for(b=0; b<co; b++)
				f[a][b] = 0;
		}

		for(a=0; a<st; a++){    //数组石头位置标记
			cin>>pr>>pc;
			f[pr-1][pc-1] = 1;
		}

		for(a=0; a<ro; a++){    //数组按行计算可行位置数量
			text = 0;
			for(b=0; b<co; b++){
				if(f[a][b] == 0){
					++text;
				}
				else{
					if(text>1){
						++num;
					}
					text=0;
				}
			}
			if(text>1){
				++num;
			}
		}

		for(b=0; b<co; b++){     //数组按列计算可行位置数量
			text=0;
			for(a=0; a<ro; a++){
				if(f[a][b] == 0){
					++text;
				}
				else{
					if(text>1){
						++num;
					}
					text=0;
				}
			}
			if(text>1){
				++num;
			}
		}
		cout<<num<<endl;
		for(a=0; a<ro; a++){   //删除一位数组
				delete[] f[a];
		}
		delete [] f;          //删除二维数组
	}
	return 0;
}

  在实现程序的过程中需要注意一些东西:
  1.如果静态定义的数组过大会溢出,因为默认的静态地址只有1—2M(忘了多少,不会大于这个范围),存不下太大的数组。
  2.如果采用全局的数组定义,可以存下很大的数组,但是文件大小就超出题目范围。
  3.使用动态分配数组可以解决以上问题,但C++中没有直接分配二维数组的,所以需要先分配一维数组,再逐个分配二维数组。
  4.动态分配并使用完后,记得删除地址空间,养成好习惯。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值