螺旋矩阵 noip2014普及组
本题可以直接模拟填数字,也可以直接计算结果。
代码一:(这个代码,缺陷在于数组太大,浪费内存啊。另外,循环次数也不少。总之,时间空间的消耗都不小。)
/*===============================================================
本段代码是模拟往数组填数字的过程。
每填写一个值就判断该位置是否(i,j)。若寻到目标位置,
则输出答案。
=================================================================*/
#include<stdio.h>
int a[][]={};//这个大小的静态数组尚可申请,但假如是放在函数内部声明却不行了的。这个大小大概是9MB,但距离30000*30000的大小实在是太远了。
int main()
{
int n,i,j;
int m;//m表示总共的层数
int k,p,q;//循环变量
int flag=;//标志性变量:等于0表示尚未循环到目标元素(i,j)
int t;
int len; scanf("%d%d%d",&n,&i,&j);
m=(n+)/; //m表示总共的层数
t=; //t表示要填进数组的数字
for(k=;k<=m&&flag==;k++)
{
p=k,q=k; //(k,k)是第k层左上角坐标点
len=n-*(k-);//表示当前层中每一条边的元素个数
for(;q<=(k+len-);q++)//填充当前层的顶边
{
a[p][q]=t;
if(p==i&&q==j)
{
printf("%d\n",a[p][q]);
return ;
}
t++;
}
q--;
p++;
for(;p<=(k+len-);p++)//填充当前层的右边
{
a[p][q]=t;
if(p==i&&q==j)
{
printf("%d\n",a[p][q]);
return ;
}
t++;
}
p--;
q--;
for(;q>=k;q--)//填充当前层的下边
{
a[p][q]=t;
if(p==i&&q==j)
{
printf("%d\n",a[p][q]);
return ;
}
t++;
}
q++;
p--;
for(;p>k;p--)//填充当前层的左边
{
a[p][q]=t;
if(p==i&&q==j)
{
printf("%d\n",a[p][q]);
return ;
}
t++;
}
}
return ;
}
代码二:(这个代码缺陷在于循环时间没减少……)
/*===============================================================
本段代码也是模拟往数组填数字的过程。但没有申请数组内存来存储数据。
而是只用一个变量表示每一次要填写的数字。
毕竟题目只要输出(i,j)位置的值,故不用保存整个数组。
只需要判断每一次模拟到的位置是否是(i,j)即可。
=================================================================*/
#include<stdio.h>
int main()
{
int n,i,j;
int m;//m表示总共的层数
int k,p,q;//循环变量
int flag=;//标志性变量:等于0表示尚未循环到目标元素(i,j)
int t;
int len; scanf("%d%d%d",&n,&i,&j);
m=(n+)/; //m表示总共的层数
t=; //t表示要填进数组的数字
for(k=;k<=m&&flag==;k++)
{
p=k,q=k; //(k,k)是第k层左上角坐标点
len=n-*(k-);//表示当前层中每一条边的元素个数
for(;q<=(k+len-);q++)//填充当前层的顶边
{
if(p==i&&q==j)
{
printf("%d\n",t);
return ;
}
t++;
}
q--;
p++;
for(;p<=(k+len-);p++)//填充当前层的右边
{
if(p==i&&q==j)
{
printf("%d\n",t);
return ;
}
t++;
}
p--;
q--;
for(;q>=k;q--)//填充当前层的下边
{
if(p==i&&q==j)
{
printf("%d\n",t);
return ;
}
t++;
}
q++;
p--;
for(;p>k;p--)//填充当前层的左边
{
if(p==i&&q==j)
{
printf("%d\n",t);
return ;
}
t++;
}
}
return ;
}
代码三:(这个代码应该算是比较完美了,时间空间都降下来了,而且是O(1)时间的算法。)
/*===============================================================
本段代码不是模拟填写数字的过程,而是直接根据i和j的值计算(i,j)所在的层k。
然后计算第k层左上角(k,k)位置处的元素值。
接下来呢,要寻到 (i,j)处的值,可以有两种方法:
(1)模拟填数字的过程环绕一圈寻找(i,j)。
(2)根据i,j的值依次计算(k,k)距离(i,j)的几个段的距离即可得到答案。
这里使用第二个方案。
=================================================================*/
#include<stdio.h>
int main()
{
int n,i,j;
int k,t;
freopen("matrix10.in","r",stdin);
freopen("matrix10.txt","w",stdout);
scanf("%d%d%d",&n,&i,&j);
//根据i判断(i,j)所在层数k
t=(n+)/;
if(i<=t)
{
if(j<=t) k=(i<=j?i:j);//(i,j)在左上部分
else k=(i<(n+-j)?i:(n+-j)); //(i,j)在右上部分
}
else
{
if(j<=t) k=(n+-i)<j?(n+-i):j; //(i,j)在左下部分
else k=(n+-i)<(n+-j)?(n+-i):(n+-j); //(i,j)在右下部分
}
//计算第k层左上角坐标为(k,k)的数t
k--;
t=n*n-(n-*k)*(n-*k)+;//注意:n-2k表示剥去k层之后剩余部分的行数和列数.(i,j)所在层没被剥掉,故而要先执行k--。
k++;
if(i==k) //(i,j)在第k环的上边线
t=t+(j-k);
else if(j==k+n-*(k-)-) //(i,j)在环的右边.
t=t+(n-*(k-)-)+(i-k);
else if(i==k+n-*(k-)-)//(i,j)在环的下边
t=t+(n-*(k-)-)+(n-*(k-)-)+((k+n-*(k-)-)-j);
else t=t+(n-*(k-)-)+(n-*(k-)-)+(n-*(k-)-)+((k+n-*(k-)-)-i);
printf("%d\n",t);
return ;
}
关于计算层数的代码:
其实是把整个数组分为左上、右上、左下和右下四个区域分别处理。
#include<stdio.h>
int main()
{
int n,i,j,k,t;
scanf("%d",&n);
for(i=;i<=n;i++)
{
for(j=;j<=n;j++)
{
t=(n+)/;
if(i<=t)
{
if(j<=t) k=(i<=j?i:j);//(i,j)在左上部分
else k=(i<(n+-j)?i:(n+-j)); //(i,j)在右上部分
}
else
{
if(j<=t) k=(n+-i)<j?(n+-i):j; //(i,j)在左下部分
else k=(n+-i)<(n+-j)?(n+-i):(n+-j); //(i,j)在右下部分
}
printf("%d ",k);
}
printf("\n");
}
return ;
}
关于计算(i,i)处的值:
n*n-(n-2*k)*(n-2*k)+1
其中,n*n是数字总的个数,k是表示被剥去的层数(注意:假如(i,j)在第k层,则被剥去的是(k-1)层。)
(n-2*k)*(n-2*k)表示剥去之后,剩余部分的元素的个数。
如何理解n-2*k呢?其实啊,就是“每剥去一层,行和列的数量都会减少2,于是总共减少的数量就是2*k。剩余的部分自然就是n-2*k了。”
螺旋矩阵 noip2014普及组的更多相关文章
- noip201403螺旋矩阵【普及组】数学算法
思路如下: 1.输入n>>a>>b; 2.用一个循环缩小范围求出a,b所示的数所在的圈数q; 3.再一个循环求出圈数q的第1个数的值sum; 4.用四个if判断a,b所示的数在 ...
- 【NOIP2014 普及组】螺旋矩阵
[NOIP2014 普及组]螺旋矩阵 一.题目 [NOIP2014 普及组]螺旋矩阵 时间限制: 1 Sec 内存限制: 128 MB 提交: 18 解决: 0 [提交][状态][讨论版] 题目描 ...
- [NOIP2014] 普及组
珠心算测验 模拟. 将所有“两个不同数之和”装进桶里,扫描原数组记录满足条件的数的个数. /*by SilverN*/ #include<iostream> #include<alg ...
- noip2014普及组——珠心算测验
题目描述 珠心算是一种通过在脑中模拟算盘变化来完成快速运算的一种计算技术.珠心算训练,既能够开发智力,又能够为日常生活带来很多便利,因而在很多学校得到普及. 某学校的珠心算老师采用一种快速考察珠 ...
- [NOIP2014普及组]子矩阵
题目:洛谷P2258.Vijos P1914.codevs 3904. 题目大意:给你一个矩阵,要你找一个r行c列的子矩阵,求最小分值(子矩阵和分值的定义见原题). 解题思路:n和m比较小,考虑暴力. ...
- noip2014普及组 比例简化
题目描述 在社交媒体上,经常会看到针对某一个观点同意与否的民意调查以及结果.例如,对某一观点表示支持的有1498 人,反对的有 902人,那么赞同与反对的比例可以简单的记为1498:902. 不过,如 ...
- [NOIP2014普及组T1]珠心算测验 - NTT
求数组有多少个数,恰好等于集合中另外两个(不同的)数之和? 注意到数集比较小,而且涉及到下标的加法,可以很自然地想到卷积 注意减去自己加自己的贡献 真是一道NTT练手好题 #include <i ...
- SYCOJ246螺旋矩阵
题目-螺旋矩阵 (shiyancang.cn) noip201403螺旋矩阵[普及组]数学算法 - 大本营 - 博客园 (cnblogs.com) 以下为搬运代码.一个为算圈数,另外一个是数学方法 思 ...
- NOIP 2014 普及组 T3 螺旋矩阵
[题意] 已知:n,r,c(n<=30000) 条件:给定n行n列的螺旋矩阵(从矩阵的左上角(1,1)出发,初始时向右移动:如果前方是未曾经过的格子, 则继续前进,否则右转:重复上述操作直至经过 ...
随机推荐
- Windows下adb push 总是提示Failed to copy "XX.apk" to 'system/app':Read-only file system
一般情况看到这种提示我们会想到需要root权限,然后敲上adb remount,但是当我们执行过adb remount后,提示成功,但执行push命令依旧无法完成push. 那么此时我们的做法应该是重 ...
- Java Proxy
Client---->Interface A -- -- 代理类 Class AImpl 代理类是动态生成的,借助Proxy类和InvocationHandler接口进行实 ...
- 如何编写一个编译c#控制台应用程序的批处理程序
如何编写一个编译c#控制台应用程序的批处理程序 2011-03-22 18:14 dc毒蘑菇 | 浏览 579 次 最近在网上看了一个教程,是学C#的,但是我的机子上装不上vs,所以想写一个批处理来编 ...
- 【转】 Understanding Component-Entity-Systems
http://www.gamedev.net/page/resources/_/technical/game-programming/understanding-component-entity-sy ...
- for else
- TCP的分层结构
TFTP(Trivial File Transfer Protocol,简单文件传输协议)是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂.开销不大的文件传输服务 ...
- Spring初始化 Map 和 解析Json value
单独定义Map数据结构的bean: <bean id= "expToLevelMap" class="org.springframework.beans.facto ...
- C++,栈与队列
1,头文件 #include <stack> #include <queue> 2,声明 stack<int> stackTest; queue<int> ...
- Roman to Integer
Given a roman numeral, convert it to an integer. Input is guaranteed to be within the range from 1 t ...
- Spring MVC 通过@Value注解读取.properties配置内容
第一步:在applicationContext.xml配置: <bean id="configProperties" class="org.springframew ...