基建手游
题目描述
森林探险后小明打算在家中宅一阵子,他迷上了一款基建手游。
在浩瀚的布鲁克西大陆上,有一个神秘的王国,城主小明可以选择在这个王国里圈出一块占地K*K的正方形作为自己的城池,小明希望你选出一块合适的位置,使得他的城池土地价值和最大。
输入
第一行三个整数N,M,K,表示大陆的宽和长以及占地正方形的边长。
接下来有N行,每行M个整数,表示大陆上每个地块的价值,价值可能为负数。
1=<N, M<=1000, 1=<k<=min(N, M)
输出
一行两个整数X,Y表示小明城池左上角的坐标
样例输入
3 4 1
1 2 3 1
-1 9 0 2
2 0 1 1
样例输出
2 2
#include<iostream>
using namespace std;
int n,m,k;
int a[1005][1005],b[1005][1005];
int main() {
scanf("%d%d%d",&n,&m,&k);
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
scanf("%d",&a[i][j]);
b[i][j]=b[i-1][j]+b[i][j-1]-b[i-1][j-1]+a[i][j]; //前缀和
/*1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1 */
/*1 2 3 4
2 4 6 8
3 6 9 12
4 8 12 16*/
}
}
int maxn=-99999999;
int xx,yy;
k--;
for(int i=1; i<=n-k; i++) {
for(int j=1; j<=m-k; j++) {
int sum=b[i+k][j+k]-b[i+k][j-1]-b[i-1][j+k]+b[i-1][j-1];
if(sum>maxn) {
xx=i,yy=j;
maxn=sum;
}
}
}
cout<<xx<<' '<<yy;
}
本题考查前缀和,代码中间已经列举了最简单的前缀和,帮助同学们快速理解。
前缀和:
核心代码:b[i][j]=b[i-1][j]+b[i][j-1]-b[i-1][j-1]+a[i][j];这是二维数组中的前缀和
对于此题,开始使用的是暴力求解,很明显时间超限,然后对此类题进行了百度求解,才知道了前缀和。
敏感的小明同学
题目描述
小明是一个对数字非常敏感的人,当他看到某个特定的数字p (1<=p<=9)时就会兴奋一下,现在给你一个数值区间( l , r ),问你当小明看到这个区间内所有的数字时会兴奋多少下?(例如 l=2,r=22,p=2时,小明会兴奋6下,l=2,12,20,21时各兴奋一下,22兴奋两下)
输入
首先輸入一个整数 t,以下再输入t行数据。(t<=10000)
每行输入三个整数 l , r , p. (1<=l<=r<=10^8 ,1<=p<=9)
输出
输出t行,每行一个整数表示小明兴奋的次数。
样例输入
1 2 22 2
样例输出
6
#include<iostream>
using namespace std;
int l,r;
int p;
int f(int x) {
int a=x,t=1,s=0;
while(x) {
s+=x/10*t;
if(x%10>p)s+=t;
else if(x%10==p)s+=a%t+1;
x/=10;
t*=10;
}
return s;
}
int main() {
int t;
cin>>t;
while(t--) {
cin>>l>>r>>p;
cout<<f(r)-f(l-1)<<endl;
}
return 0;
}
对于此题,意思就是从数字r到l,数字p一共出现多少次;
这道题的思路是从数的个位上出现的p全部找出来,然后再找十位上的p,以此类推;
举例:
0 222 2
第一步 s+=x/10*t; 1-10...210..220,二在个位上出现一共有22次
(x%10==p)s+=a%t+1; 这次还得加一 共23次,这次是222的最后一个二
然后x除十,t乘十
第二步 判断十位上的s+=x/10*t 20...29 120..129; 共计20次
(x%10==p)s+=a%t+1; 这又是三次 220 221 222 记住只看十位上的二;
然后x除十,t乘十
第三步 判断百位上的二 (x%10==p)s+=a%t+1 200.....222 注意只看百位上的二
22+1=23次
所以一共23+23+23=69次;
森林探险
题目描述
小明是个方向感极弱的人,为了证明自己,他打算进入森林探险。
他的朋友小红给了他一个写满坐标的地图,如果他按照地图上的点一通过并且最终记住自己向左转动(不包括向后转动)了几次的话,就算小明胜利。
望着地图上密密麻麻的坐标轴,小明头都大了,但是聪明的他立刻想到了你:算法神犇!
你可以帮助他完成这一挑战吗?
输入
第一行一个整数n(3<=n<=1000)
下面n行每行包含两个数,为每个点的坐标x,y(0=x<=1000,0<=y<=1000),第一个点为起始点,小明行走的顺序为给出的点的顺序.
输出
一个整数。(小明向左转动的次数,不包括向后转动)
样例输入
6 0 0 0 1 1 1 1 2 2 2 2 0
样例输出
1
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<stack>
#include<algorithm>
#include<math.h>
using namespace std;
struct P {
int x;
int y;
} feng[2000],p1,p2;
double judge(P p1,P p2,P p3) {
return ((p2.x-p1.x)*(p3.y-p2.y)-(p2.y-p1.y)*(p3.x-p2.x)); //叉乘向量a叉乘向量b等于向量a的模乘向量b的模乘sin&;&是角度值,向量a叉乘向量b一向量a为x轴逆时针旋转是&的值
}
int main() {
int n;
scanf("%d",&n);
for(int i=0; i<n; i++) {
scanf("%d%d",&feng[i].x,&feng[i].y);
}
int count=0;
for(int i=2; i<n; i++) {
if(judge(feng[i-2],feng[i-1],feng[i])>0)count++; //第一步没方向 从第三步开始算
}
printf("%d\n",count);
return 0;
}
对于此题 主要考二维向量叉积的几何意义
叉积的几何意义有三:
1、A*B=|A|·|B|·sinα.
其中α表示A到B的夹角,用以判断该角度是正或者负。这个结论可用于四个点中任意三个点构成的三角形,判断另外一个点是否在三角形中,那么四个点构成三个向量叉积的结果就能判断。
2、A*B=x1*y2-x2*y1.
得到的结果应该是向量,但是取其模可以用于由A和B构成的平行四边形的面积,进而可以得到两个三角形的面积。
3、A*B=x1*y2-x2*y1.
得到的结果为一个向量,这个向量垂直于向量A和B。