NOIP2004 提高组 第1轮 初赛 五.完善程序

1.Joseph

题目描述:

原始的Joseph问题的描述如下:有n个人围坐在一个圆桌周围,把这n个人依次编号为1,…,n。从编号是1的人开始报数,数到第m个人出列,然后从出列的下一个人重新开始报数,数到第m个人又出列,…,如此反复直到所有的人全部出列为止。比如当n=6,m=5的时候,出列的顺序依次是5,4,6,2,3,1。

现在的问题是:假设有k个好人和k个坏人。好人的编号的1到k,坏人的编号是k+1到2k。我们希望求出m的最小值,使得最先出列的k个人都是坏人。

输入:

仅有的一个数字是k(0 < k <14)。

输出:

使得最先出列的k个人都是坏人的m的最小值。

输入样例:

4

输出样例:

30

程序:

#include <stdio.h>
long k, m, begin;
int check(long remain){
	long result = (  ①  ) % remain;
	if (  ②  ){
		begin = result; return 1;
	}
	else return 0;
}
int main(){
	long i, find = 0;
	scanf("%ld", &k);
	for (m = k;   ③  ; m++){
		find = 1; begin = 0;
		for (i = 0; i < k; i++)
			if (!check(  ④  )){
				find = 0; break;
			}
	}
	printf("%ld\n",   ⑤  );
	return 0;
}

2.逻辑游戏

题目描述:

一个同学给了我一个逻辑游戏。他给了我图1,在这个图上,每一段边界都已经进行了编号。我的任务是在图中画一条连续的曲线,使得这条曲线穿过每一个边界一次且仅穿过一次,而且曲线的起点和终点都在这整个区域的外面。这条曲线是容许自交的。

对于图1,我的同学告诉我画出这样的一条曲线(图2)是不可能的,但是对于有的图形(比如图3),画出这样一条曲线是可行的。对于给定的一个图,我想知道是否可以画出满足要求的曲线。

 输入:

输入的图形用一个n×n的矩阵表示的。矩阵的每一个单元里有一个0到255之间(包括0和255)的整数。处于同一个区域的单元里的数相同,相邻区域的数不同(但是不相邻的区域里的数可能相同)。

输入的第一行是n(0<n<100)。以下的n行每行包括n个整数,分别给出对应的单元里的整数(这n个整数之间用空格分开)。图4给出了输入样例对应的图形。

输出:

当可以画出满足题意的曲线的时候,输出“YES”;否则,输出“NO”。

输入样例:

3

1 1 2

1 2 2

1 1 2

输出样例:

YES

程序:

#include <stdio.h>
#include <math.h>
int orig, n, ns, a[102][102], bun;
int d[]={1, 0, -1, 0, 0, 1,   ①  };
void plimba(int x, int y){
	int i, x1, y1;
	a[x][y] = -a[x][y];
	if (abs(a[x - 1][y]) != orig && (  ②   != a[x - 1][y]
|| abs(a[x][y - 1]) != orig)) ns++;
	if (abs(a[x + 1][y]) != orig && (a[x + 1][y - 1] != a[x + 1][y]
|| abs(a[x][y - 1]) != orig)) ns++;
	if (abs(a[x][y - 1]) != orig && (  ③   != a[x][y - 1]
|| abs(a[x - 1][y]) != orig)) ns++;
	if (abs(a[x][y + 1]) != orig && (a[x - 1][y + 1] != a[x][y + 1]
|| abs(a[x - 1][y]) != orig)) ns++;
	for (i = 0; i < 4; i++){
		x1 = x + d[2 * i]; y1 = y +   ④  ;
	if (x1 >= 1 && x1 <= n && y1 >= 1 && y1 <= n &&   ⑤  )
plimba(x1, y1);
	}
}
int main(){
	int i, j;
	bun = 1;
	scanf("%d", &n);
	for (i = 0; i <= n+1; i++)
 		for (j = 0; j <= n+1; j++) a[i][j] = 0;
	a[0][0] = -1; a[n + 1][0] = -1; 
	a[0][n + 1] = -1; a[n + 1][n + 1] = -1;
	for (i = 1; i <= n; i++) 
		for ( j = 1; j <= n; j++) scanf("%d", &(a[i][j]));
	for (i = 1; i <=n ; i++)
		for (j = 1; j <= n; j++){
			if (a[i][j] > -1){
				ns = 0;   ⑥  ;
				plimba(i, j);
				if (ns % 2 == 1)bun = 0;
			}
		}
	if (bun) printf("YES\n"); else printf("NO\n");
	return 0;
}

答案:

1.

(1)      begin+m-1                                   

(2)      result>=k  (或者k<=result)                              

(3)     !find (或者 find==0)                            

(4)      2*k-i                           

(5)      m-1                                                  

2.

 (1)     0,-1

(2)    a[x-1][y-1]

(3)    a[x-1][y-1] 

(4)    d[2*i+1]

(5)    a[x1][y1]==orig (或者orig==a[x1][y1])

(6)    orig=a[i][j]



 


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
约瑟夫问题是一个经典的问题,我们不妨将这个经典问题进行扩展,变成一个双向的约瑟夫问题。   已知n个人(不妨分别以编号1,2,3,…,n 代表 )围坐在一张圆桌周围,首先从编号为 k 的人从1开始顺时针报数,1, 2, 3, ...,记下顺时针数到 m 的那个人,同时从编号为 k 的人开始逆时针报数,1, 2, 3, ...,数到 m 后,两个人同时出列。然后从出列的下一个人又从 1 开始继续进行双向报数,数到m的那两个人同时出列,…;。依此重复下去,直到圆桌周围的人全部出列。直到圆桌周围只剩一个人为止。   如果双向报数报到 m 时落在同一个人身上,那本次出列的只有一个人。   例如:5,1,2。则总共5个人,从1开始顺时针报数,数到2,定位编号2;同时从1开始报数数到2,定位编号5;2和5同时出列。然后继续开始报数,顺时针报数3,4,定位到4;逆时针报数4,3,定位3;4和3同时出列。最后剩余的为编号1。输出为:2-5,4-3,1,。   如果输入:6,2,3。则输出:4-6,2,1-3,5,。其中第2次只输出一个2,表示第二次双向报数时,恰好都落在编号2上,所以只有一个编号出列。 输入 n,k,m 输出 按照出列的顺序依次输出编号。同时出列编号中间用减号“-”连接。 非法输入的对应输出如下 a) 输入:n、k、m任一个为0 输出:n,m,k must bigger than 0. b) 输入:k>n 输出:k should not bigger than n.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dllglvzhenfeng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值