每个测试输入包含1个测试用例,第一行包括两个整数 N 和 D : 3 <= N <= 100 1 <= D <= N 接下来有N行,每行N个数字d: 0 <= d <= 100
输出一个整数,表示找到的和的最大值
4 2 87 98 79 61 10 27 95 70 20 64 73 29 71 65 15 0
193
#include<iostream> #include<string> using namespace std; int maps[105][105]; int map1[105][105]; int map2[105][105]; int map3[105][105]; int map4[105][105]; /*初始化四个数组,分别表示水平相加,竖直相加,主对角线,次对角线 对于水平相加的数组,a[i][j]表示第i行前j个元素相加,竖直相加的数组类似 对于主对角线的数组,a[i][j]表示第i行第j列所在的元素所在的对角线的叠加,次对角线类似 这样做是在计算的时候减少了一层循环,减少时间复杂度 */ void init(int n){ ///水平相加 for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ map1[i][j]=map1[i][j-1]+maps[i][j]; } } ///竖直相加 for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ map2[i][j]=map2[i-1][j]+maps[i][j]; } } ///主对角线相加 for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ map3[i][j]=map3[i-1][j-1]+maps[i][j]; } } ///次对角线相加 for(int i=1;i<=n;i++){ for(int j=n;j>=1;j--){ map4[i][j]=map4[i-1][j+1]+maps[i][j]; } } } int main() { int N,D; cin>>N>>D; for(int i=1;i<=N;i++){ for(int j=1;j<=N;j++){ cin>>maps[i][j]; } } init(N); int ans=0; int r1,r2,r3,r4; for(int i=1;i<=N;i++){ for(int j=1;j<=N;j++){ r1=r2=r3=r4=0; if(j>=D){ r1=map1[i][j]-map1[i][j-D]; } if(i>=D){ r2=map2[i][j]-map2[i-D][j]; } if(i>=D&&j>=D){ r3=map3[i][j]-map3[i-D][j-D]; ///这里次对角线的处理,比较特殊,需要对于j向后平移一个 r4=map4[i][j-D+1]-map4[i-D][j+1]; } ans=max(ans,max(max(r1,r2),max(r3,r4))); } } cout<<ans<<endl; return 0; }
import java.util.*; public class Main{ public static void main(String args[]){ Scanner in=new Scanner(System.in); int n=in.nextInt(); int d=in.nextInt(); int a[][]=new int[n][n]; for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ a[i][j]=in.nextInt(); } } int max1=Math.max(heng(a,n,d),shu(a,n,d)); int max2=Math.max(zuoxie(a,n,d),youxie(a,n,d)); System.out.println(Math.max(max1,max2)); } static int heng(int[][] a,int n,int d){ int max=0; for(int j=0;j<n;j++){ int l=0,r=d-1;int sum=0; for(int i=0;i<d;i++){ sum+=a[j][i]; } max=Math.max(sum,max); while(r+1<n){ max=Math.max(max,sum+a[j][++r]-a[j][l]);sum+=a[j][r]-a[j][l];l++; } } return max; } static int shu(int[][] a,int n,int d){ int max=0; for(int j=0;j<n;j++){ int l=0,r=d-1;int sum=0; for(int i=0;i<d;i++){ sum+=a[i][j]; } max=Math.max(sum,max); while(r+1<n){ max=Math.max(max,sum+a[++r][j]-a[l][j]);sum+=a[r][j]-a[l][j];l++; } } return max; } static int zuoxie(int[][] a,int n,int d){ int max=0; for(int j=0;j<=n-d;j++){ int l1=j,l2=0,r1=j,r2=0;int sum=0; for(;r2<d;r2++,r1++){ sum+=a[r1][r2]; } r2--;r1--; max=Math.max(sum,max); while(r1+1<n){ max=Math.max(max,sum+a[++r1][++r2]-a[l1][l2]);sum+=a[r1][r2]-a[l1][l2];l1++;l2++; } } for(int j=1;j<=n-d;j++){ int l1=0,l2=j,r1=0,r2=j;int sum=0; for(;r1<d;r2++,r1++){ sum+=a[r1][r2]; } r2--;r1--; max=Math.max(sum,max); while(r2+1<n){ max=Math.max(max,sum+a[++r1][++r2]-a[l1][l2]);sum+=a[r1][r2]-a[l1][l2];l1++;l2++; } } return max; } static int youxie(int[][] a,int n,int d){ int max=0; for(int j=d-1;j<n;j++){ int l1=j,l2=0,r1=j,r2=0;int sum=0; for(;r2<d;r2++,r1--){ sum+=a[r1][r2]; } r2--;r1++; max=Math.max(sum,max); while(r1-1>=0){ max=Math.max(max,sum+a[--r1][++r2]-a[l1][l2]);sum+=a[r1][r2]-a[l1][l2];l1--;l2++; } } for(int j=1;j<=n-d;j++){ int l1=n-1,l2=j,r1=n-1,r2=j;int sum=0; for(;r1>=n-d;r2++,r1--){ sum+=a[r1][r2]; } r2--;r1++; max=Math.max(sum,max); while(r2+1<n){ max=Math.max(max,sum+a[--r1][++r2]-a[l1][l2]);sum+=a[r1][r2]-a[l1][l2];l1--;l2++; } } return max; } }
#include<iostream> usingnamespacestd; intmain() { intjie, num, array[10][10], k = 0; cin >> jie >> num; intright, low; intcount, out[100] = {0}; for(inti = 0; i < jie; ++i) { for(intj = 0; j < jie; ++j) { right = jie - i - num; low = jie - j - num; count = 0; if(right >= 0 && low >= 0) { while(num--) { count += array[i+num-1][j+num-1]; } out[k++] = count; } count = 0; if(right >= 0 && low < 0) { while(num--) { count += array[i][j + num - 1]; } out[k++] = count; } count = 0; if(right < 0 && low >= 0) { while(num--) { count += array[i+num-1][j]; } out[k++] = count; } } } intmax = out[0]; for(intm = 1; m < k; ++m) { if(out[m] > max) { max = out[m]; } } cout << max; return0; } |
//维护四个前缀和 #include <cstdio> #include <cstring> #include <algorithm> usingnamespacestd; intn, d, a[110][110], srow[110][110], scol[110][110], srd[110][110], sld[110][110]; intmain() { scanf("%d%d", &n, &d); for(inti = 1; i <= n; i++) for(intj = 1; j <= n; j++) scanf("%d", &a[i][j]); for(inti = 1; i <= n; i++) for(intj = 1; j <= n; j++) { srow[i][j] = srow[i][j-1] + a[i][j]; scol[j][i] = scol[j][i-1] + a[i][j]; srd[i][j] = srd[i-1][j-1] + a[i][j]; sld[i][j] = sld[i-1][j+1] + a[i][j]; } intans = 0; for(inti = 1; i <= n; i++) for(intj = 1; j <= n; j++) { intli = i - d, lj = j - d, rj = j+d; if(lj >= 0) ans = max(ans, srow[i][j] - srow[i][lj]); if(li >= 0) ans = max(ans, scol[j][i] - scol[j][li]); if(li >= 0 && lj >= 0) ans = max(ans, srd[i][j] - srd[li][lj]); if(li >= 0 && rj <= n+1) ans = max(ans, sld[i][j] - sld[li][rj]); } printf("%d\n", ans); return0; }
#include <bits/stdc++.h>usingnamespacestd;intrl( vector<vector<int> > dp, intN, intD){intres = 0;for(inti = 0; i<N; i++){for(intj = 0; j<N-D+1; j++){inttmp = 0;for(intt = 0; t<D; t++){tmp += dp[i][j + t];}res = max(res, tmp);}}returnres;}inttb( vector<vector<int> > dp, intN, intD){intres = 0;for(inti = 0; i<N-D+1; i++){for(intj = 0; j<N; j++){inttmp = 0;for(intt = 0; t<D; t++){tmp += dp[i+t][j];}res = max(res, tmp);}}returnres;}intrl1( vector<vector<int> > dp, intN, intD){intres = 0;for(inti = 0; i<N-D+1; i++){for(intj = 0; j<N-D+1; j++){inttmp = 0;for(intt = 0; t<D; t++){tmp += dp[i+t][j + t];}res = max(res, tmp);}}returnres;}inttb1(vector<vector<int> > dp, intN, intD){intres = 0;for(inti = 0; i < N-D +1; i++){for(intj = N-1; j >= D -1; j--){inttmp = 0;for(intt = 0; t<D; t++){tmp += dp[i + t][j - t];}res = max(res, tmp);}}returnres;}intmain(){intN,D;while(cin>>N>>D){vector<vector<int> > dp;vector<int> v;intd;for(inti=0;i<N;i++){v.clear();for(intj=0;j<N;j++){cin>>d;v.push_back(d);}dp.push_back(v);}intmax1=rl(dp,N,D);intmax2=tb(dp,N,D);intmax3=rl1(dp,N,D);intmax4=tb1(dp,N,D);intres =max(max(max(max1,max2),max3),max4);cout<<res<<endl;}return0;}
//为什么用java写的人辣么少呢,,, //这个感觉不是很难,就是有点复杂代码。。。 import java.util.Scanner; /** * Created by huali on 2018/5/25. */ public class Main { // 在一个N*N的数组中寻找所有横,竖,左上到右下,右上到左下, // 四种方向的直线连续D个数字的和里面最大的值 //输入描述: //每个测试输入包含1个测试用例,第一行包括两个整数 N 和 D : //3 <= N <= 100 //1 <= D <= N //接下来有N行,每行N个数字d: //0 <= d <= 100 // // //输出描述: //输出一个整数,表示找到的和的最大值 // //输入例子1: //4 2 //87 98 79 61 //10 27 95 70 //20 64 73 29 //71 65 15 0 // //输出例子1: //193 public static void main(String []args) { Scanner sr = new Scanner(System.in); while (sr.hasNext()) { int N = sr.nextInt(); int D = sr.nextInt(); int [][]arr = new int[N][N]; for(int i=0;i<N;i++) { for(int j=0;j<N;j++) { arr[i][j] = sr.nextInt(); } } int max= 0; for (int i = 0; i < N; ++i) { for (int start = 0; start <= N-D; ++start) { int sum=0; for (int k = 0; k < D; ++k) { sum+=arr[i][start+k]; } max = Math.max(max, sum); } } for (int i = 0; i < N; ++i) { for (int start = 0; start <= N-D; ++start) { int sum=0; for (int k = 0; k < D; ++k) { sum+=arr[start+k][i]; } max = Math.max(max, sum); } } for(int i=0;i<N;i++) { //按照列 for(int j=0;j<N;j++) { int temp = 0; if(i+D-1>=0&&i+D-1<N&&j-D+1>=0&&j-D+1<N) { for (int k = 0; k < D; ++k) { temp += arr[i+k][j-k]; } max = Math.max(max, temp); } } //max = Math.max(max, temp); } for(int i=0;i<N;i++) { //按照列 //int temp = 0; for(int j=0;j<N;j++) { int temp = 0; if(i+D-1>=0&&i+D-1<N&&j+D-1>=0&&j+D-1<N) { for (int k = 0; k < D; ++k) { temp += arr[i+k][j+k]; } max = Math.max(max, temp); } } //max = Math.max(max, temp); } System.out.println(max); } sr.close(); } }
//使用积分图加快运算
#include <iostream> #include <vector> #include <string> #include <algorithm> int main() { using namespace std; int n, d; while (cin >> n >> d) { vector<vector<int> > matrix(n, vector<int>(n, 0)); for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) cin >> matrix[i][j]; int ans = 0; for (int i = 0; i < n; i++) { for (int j = 0; j <= n - d; j++) { int ret = 0; for (int k = j; k < j + d; k++) { ret += matrix[i][k]; } if (ret > ans) ans = ret; } } for (int i = 0; i < n; i++) { for (int j = 0; j <= n - d; j++) { int ret = 0; for (int k = j; k < j + d; k++) { ret += matrix[k][i]; } if (ret > ans) ans = ret; } } for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { int ret = 0; for (int k = 0; k < d; k++) { if (i + k >= n || j + k >= n) break; ret += matrix[i + k][j + k]; } if (ret > ans) ans = ret; } } for (int i = 0; i < n - d + 1; i++) { for (int j = n - 1; j >= 0; j--) { int ret = 0; for (int k = 0; k < d; k++) { if (i + k >= n || j - k < 0) break; ret += matrix[i + k][j - k]; } if (ret > ans) { ans = ret; } } } cout << ans << endl; } return 0; }
#include <iostream>#include <string> using namespace std; int main() { int n, d, a[101][101]; scanf("%d%d", &n, &d); for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { scanf("%d", &a[i][j]); } } int ans = 0; for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { int temp; if (n - j >= d) { //横 temp = 0; for (int k = j; k < j + d; ++k) { temp += a[i][k]; } ans = max(temp, ans); } if (n - i >= d) { //竖 temp = 0; for (int k = i; k < i + d; ++k) { temp += a[k][j]; } ans = max(ans, temp); } if (n - i >= d && n - j >= d) { //左上到右下 temp = 0; for (int k = i, l = j; k < i + d, l < j + d; ++k, ++l) { temp += a[k][l]; } ans = max(ans, temp); } if (n - i >= d && j >= d - 1) { //右上到左下 temp = 0; for (int k = i, l = j; k < i + d, l > j - d; ++k, --l) { temp += a[k][l]; } ans = max(ans, temp); } } } cout << ans << endl; return 0; }
卡最后一个案例 的注意题意 ,连续的D个数,也就是不包括小于D个数的答案, 当然讲道理D个数的和 大于D-1 个数的和,算不算都无所谓,但是不包括有负数的情况,所以会出现极端情况,D-1个数的 和大于D个数和,所以避免计算小于D个数的和,这样不会卡最后一个案例 #include<bits/stdc++.h> using namespace std; const int N=100; int arr[N][N]; int main() { int i,j,k; int n,d; int sum=0; int ans[N][N]; cin>>n>>d; for(i=0; i<n; i++){ for(j=0; j<n; j++){ cin>>arr[i][j]; } } int m1 = 0;//横行 for(i=0; i<n; i++){ for(j=0; j<n; j++){ sum = 0; for(k=0; k<d; k++){ if(j+k>=n) break; sum += arr[i][j+k]; } if(m1 < sum){ m1 = sum; } } } //cout<<m1<<endl; int m2=0; //竖列 for(i=0; i<n; i++){ for(j=0; j<n; j++){ sum = 0; for(k=0; k<d; k++){ if(j+k>=n) break; sum += arr[j+k][i]; } if(m2 < sum){ m2 = sum; } } } //cout<<m2<<endl; int m3=0; //左上到右下 for(i=0; i<n; i++){ for(j=0; j<n; j++){ sum = 0; for(k=0; k<d; k++){ if(i+k>= n || j+k >= n) break; sum += arr[i+k][j+k]; } if(m3<sum){ m3 = sum; } } } //cout<<m3<<endl; int m4=0; //右上到左下 for(i=0; i<n-d+1; i++){ for(j=n-1; j>=0; j--){ sum = 0; for(k=0; k<d; k++){ if(i+k>=n || j-k<0 ) break; sum += arr[i+k][j-k]; } //cout<<sum<<" "; if(m4<sum){ m4 = sum; } } } //cout<<m4<<endl; int ma=0; ma = max(ma,m1); ma = max(ma,m2); ma = max(ma,m3); ma = max(ma,m4); cout<<ma<<endl; return 0; }
import java.util.Scanner; public class Main{ public static void main(String args[]){ Scanner scan = new Scanner(System.in); int N = 0; int D = 0; N = scan.nextInt(); D = scan.nextInt(); int[][] nums = new int[N][N]; for(int i = 0; i < N; i++){ for(int j = 0; j < N; j++){ nums[i][j] = scan.nextInt(); } } int max = 0; //确定各方向的第一个值的索引 for(int k = 0; k < N; k++){ //确定各方向连续D个值的开始索引 for(int begin = 0; begin <= N-D; begin++){ //横 int hsum = 0; //竖 int ssum = 0; //左上到右下1 int lsum1 = 0; //左上到右下2 int lsum2 = 0; //右上到左下1 int rsum1 = 0; //右上到左下2 int rsum2 = 0; //开始求各方向连续D个数的和 for(int m = 0; m < D; m++){ hsum += nums[k][begin+m]; ssum += nums[begin+m][k]; if((k+D+begin) <= N){ lsum1 += nums[k+begin+m][begin+m]; //避免1和2重复求k=0时的和 if(k != 0){ lsum2 += nums[begin+m][k+begin+m]; rsum2 += nums[k+begin+m][N-1-begin-m]; } } if((N-k-begin-D) >= 0){ rsum1 += nums[m+begin][N-1-k-begin-m]; } } if(hsum > max) max = hsum; if(ssum > max) max = ssum; if(lsum1> max) max = lsum1; if(lsum2 > max) max = lsum2; if(rsum1 > max) max = rsum1; if(rsum2 > max) max = rsum2; } } System.out.println(max); } }
public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); int n = input.nextInt(); int d = input.nextInt(); int arr[][] = new int[n][n]; for (int x = 0; x < n; x++) { for (int y = 0; y < n; y++) { arr[x][y] = input.nextInt(); } } int max = 0; //从每个点出发,都有四种可能,到左下角的和、到右下角的和、下垂直方向的和、右水平方向的和 //每次计算完这四个方向的和,就让top指针自增,即向右移动到下一个,该行全部计算完后,再让left下移到下一行,同时top从0开始计算 for (int left = 0; left < n; left++) { for (int top = 0; top < n; top++) { if (top + 1 - d >= 0 && left - 1 + d < n) { int temp = leftLine(arr, left, top, d); max = max > temp ? max : temp; } if (top - 1 + d < n && left - 1 + d < n) { int temp = rightLine(arr, left, top, d); max = max > temp ? max : temp; } if (top - 1 + d < n) { int temp = horizontalLine(arr, left, top, d); max = max > temp ? max : temp; } if (left - 1 + d < n) { int temp = verticalLine(arr, left, top, d); max = max > temp ? max : temp; } } } System.out.println(max); } static int leftLine(int[][] arr, int left, int top, int d) { int result = 0; for (int x = 0; x < d; x++) { result += arr[left][top]; left++; top--; } return result; } static int rightLine(int[][] arr, int left, int top, int d) { int result = 0; for (int x = 0; x < d; x++) { result += arr[left][top]; left++; top++; } return result; } static int horizontalLine(int[][] arr, int left, int top, int d) { int result = 0; for (int x = 0; x < d; x++) { result += arr[left][top]; top++; } return result; } static int verticalLine(int[][] arr, int left, int top, int d) { int result = 0; for (int x = 0; x < d; x++) { result += arr[left][top]; left++; } return result; } }
#include <iostream> (720)#include <string> #include <algorithm> using namespace std; int main() { int N, D; while (cin >> N >> D) { const int n = 100; int input[n][n]; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { cin>>input[i][j]; } } int mx = 0; // 按行 for (int i = 0; i < N; i++) { for (int j = 0; j < N-D+1; j++) { int temp = 0; int t = 0; while (t < D) { temp += input[i][j + t]; t++; } mx = max(mx, temp); } } // 按列 for (int i = 0; i < N; i++) { for (int j = 0; j < N - D + 1; j++) { int temp = 0; int t = 0; while (t < D) { temp += input[j + t][i]; t++; } mx = max(mx,temp); } } // 左上到右下 for (int i = 0; i < N-D+1; i++) { for (int j = 0; j < N - D + 1; j++) { int temp = 0; int t = 0; while (t < D) { temp += input[i + t][j + t]; t++; } mx = max(mx,temp); } } // 右上到左下 for (int i = 0; i<N-D+1; i++) { for (int j = N-1; j >D-2; j--) { int temp = 0; int t = 0; while (t < D) { temp += input[i + t][j - t]; t++; } mx = max(mx,temp); } } // total cout << mx << endl; } return 0; }
思路:对于矩阵的每一点,计算它的横,竖,右下,左下的D个数之和是否比当前最大值大,如果是则替换当前的最大值。check函数是为了判断点(x,y)是否越界 #include<iostream> using namespace std; bool check(int x, int y, int N); int main() { //输入N和D int N, D; cin >> N >> D; //输入数据 int **matrix = new int*[N]; for (int i = 0; i < N; i++) { matrix[i] = new int[N]; } //初始化矩阵 for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { cin >> matrix[i][j]; } } //计算每一点开始的最大值 int max = matrix[0][0]; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { //计算横 if (check(j + D-1, i, N)) { int count = 0; for (int k = 0; k < D; k++) { count += matrix[i][j + k]; } max = count > max ? count : max; } //计算竖 if (check(i + D - 1, j, N)) { int count = 0; for (int k = 0; k < D; k++) { count += matrix[i+k][j]; } max = count > max ? count : max; } //左上到右下 if (check(i + D - 1, j+D-1, N)) { int count = 0; for (int k = 0; k < D; k++) { count += matrix[i + k][j+k]; } max = count > max ? count : max; } //右上到左下 if (check(i + D - 1, j - D + 1, N)) { int count = 0; for (int k = 0; k < D; k++) { count += matrix[i + k][j - k]; } max = count > max ? count : max; } } } cout << max; system("pause"); return 0; } bool check(int x,int y,int N) { return (x >= 0 && x < N && 0 <= y&&y < N); }