NPOJ 1064 原原的密信

题目大意:中文

注释代码:

/*                                                    
 * Problem ID : NPOJ 1064 原原的密信
 * Author     : Lirx.t.Una                                                    
 * Language   : C++                                   
 * Run Time   : 7                                                     
 * Run Memory : 1692                                                     
*/ 

#include <algorithm>
#include <iostream>
#include <vector>
#include <cstdio>
#include <cctype>

//密信的最大宽度
#define	MAXN		21

using namespace std;

double	xo, yo;//密信的中点坐标

struct	Point {//假设密信是一个第一象限的直角坐标系
	//左下角为(1, 1)

	int		x, y;

	Point(void) {}

	Point( int xx, int yy ) : x(xx), y(yy) {}

	bool//对洞处的所有点按照从上到下从左到右的顺序进行排序
	operator<(const Point &oth)
	const {
	
		if ( y != oth.y ) return y > oth.y;
		else return x < oth.x;
	}

	void
	trans(void) {//对洞处的点进行直角旋转(顺时针)
		//旋转可以看成是相对中点旋转90度,因此求相对中点的向量(dx, dy)
		//然后做变换(dy, -dx)就得到了变换后的相对中点的向量
		//最后(x + dy, y - dx)就是最终变换后的结果
		//注意!:中点的值可能是带.5的小数,注意类型转换
	
		double	dx, dy;

		dx = (double)y - yo;
		dy = xo - (double)x;

		x = (int)( xo + dx );
		y = (int)( yo + dy );
	}
};

char	m[MAXN][MAXN];//matrix,密信
char	fmt[5];//格式化字符串

int
main() {

	int		n, l;//密信的宽度和密码的长度
	int		x, y;//计数变量,指示坐标

	int		iscn;

	char	ctmp;//临时字符变量

	iscn = 0;
	while ( ~scanf("%d%d", &n, &l) ) {
	
		vector<Point>				v;//存放所有洞处的点
		vector<Point>::iterator		it;

		//计算密信中点坐标
		xo = (double)n / 2.0 + 0.5;
		yo = xo;

		for ( y = n; y > 0; y-- )//输入密信信息
			for ( x = 1; x <= n; x++ ) {

				scanf("%s", fmt);
				m[x][y] = *fmt;
			}

		for ( y = n; y > 0; y-- )//将所有洞处的点存入v中
			for ( x = 1; x <= n; x++ ) {

				scanf("%s", fmt);
				if ( 'O' == *fmt )
					v.push_back( Point( x, y ) );
			}
		//由于初始化时点就是按照从上到下从左到右的顺序的,因此不需要排序

		printf("Case #%d: ", ++iscn);
		while ( true ) {

			for ( it = v.begin(); it != v.end() && l; it++, l-- ) {//当密码还没输完时
				//继续输出
			
				//注意还有','和'.'两种字符
				if ( ',' == ( ctmp = m[ it->x ][ it->y ] ) || '.' == ctmp )
					putchar(ctmp);
				else
					putchar(tolower(ctmp));//注意将大写改成小写
			}

			if ( !l ) break;//如果密码输完则推出

			v.erase(v.begin());//否则就先删去第一个点
			for ( it = v.begin(); it != v.end(); it++ ) it->trans();//然后再对剩余点做变换
			sort(v.begin(), v.end());//变换之后按照从上到下从左到右的顺序进行排序
		}
		putchar('\n');
	}
	
	return 0;
}

无注释代码:

#include <algorithm>
#include <iostream>
#include <vector>
#include <cstdio>
#include <cctype>

#define	MAXN		21

using namespace std;

double	xo, yo;

struct	Point {

	int		x, y;

	Point(void) {}

	Point( int xx, int yy ) : x(xx), y(yy) {}

	bool
	operator<(const Point &oth)
	const {
	
		if ( y != oth.y ) return y > oth.y;
		else return x < oth.x;
	}

	void
	trans(void) {
	
		double	dx, dy;

		dx = (double)y - yo;
		dy = xo - (double)x;

		x = (int)( xo + dx );
		y = (int)( yo + dy );
	}
};

char	m[MAXN][MAXN];
char	fmt[5];

int
main() {

	int		n, l;
	int		x, y;

	int		iscn;

	char	ctmp;

	iscn = 0;
	while ( ~scanf("%d%d", &n, &l) ) {
	
		vector<Point>				v;
		vector<Point>::iterator		it;

		xo = (double)n / 2.0 + 0.5;
		yo = xo;

		for ( y = n; y > 0; y-- )
			for ( x = 1; x <= n; x++ ) {

				scanf("%s", fmt);
				m[x][y] = *fmt;
			}

		for ( y = n; y > 0; y-- )
			for ( x = 1; x <= n; x++ ) {

				scanf("%s", fmt);
				if ( 'O' == *fmt )
					v.push_back( Point( x, y ) );
			}

		printf("Case #%d: ", ++iscn);
		while ( true ) {

			for ( it = v.begin(); it != v.end() && l; it++, l-- ) {
			
				if ( ',' == ( ctmp = m[ it->x ][ it->y ] ) || '.' == ctmp )
					putchar(ctmp);
				else
					putchar(tolower(ctmp));
			}

			if ( !l ) break;

			v.erase(v.begin());
			for ( it = v.begin(); it != v.end(); it++ ) it->trans();
			sort(v.begin(), v.end());
		}
		putchar('\n');
	}

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值