[蓝桥杯][2013年第四届真题]剪格子
如下图所示,3 x 3 的格子中填写了一些整数。
+--*--+--+
|10* 1|52|
+--****--+
|20|30* 1|
*******--+
| 1| 2| 3|
+--+--+--+
我们沿着图中的星号线剪开,得到两个部分,每个部分的数字和都是60。
本题的要求就是请你编程判定:对给定的m x n 的格子中的整数,是否可以分割为两个部分,使得这两个区域的数字和相等。
如果存在多种解答,请输出包含左上角格子的那个区域包含的格子的最小数目。
如果无法分割,则输出 0。
表示表格的宽度和高度。
接下来是n行,每行m个正整数,用空格分开。每个整数不大于10000。
3 3 10 1 52 20 30 1 1 2 3
3
dfs 4个参数,前面两个代表坐标,第三个代表不断变化的总和,最后一个是总和相等的个数,取较小者。
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <stdlib.h> #include <queue> using namespace std; const int inf=0x3f3f3f; int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; int maps[15][15]; int vis[15][15]; int n,m,all=0,ans=inf; void dfs(int x,int y,int sum,int cnt) { if(sum>all/2) return ; if(sum==all/2) ans=min(ans,cnt); else { for(int i=0;i<4;i++) { int xx=x+dir[i][0]; int yy=y+dir[i][1]; if(xx>=0&&xx<n&&yy>=0&&yy<m&&!vis[xx][yy]) { vis[xx][yy]=1; dfs(xx,yy,sum+maps[xx][yy],cnt+1); vis[xx][yy]=0; } } } } int main() { scanf("%d%d",&m,&n); for(int i=0; i<n; i++) { for(int j=0; j<m; j++) { scanf("%d",&maps[i][j]); all+=maps[i][j]; } } memset(vis,0,sizeof(vis)); vis[0][0]=1; dfs(0,0,maps[0][0],1); if(ans==inf) { cout<<0<<endl; } else { cout<<ans<<endl; } return 0; }
问题描述
给定一个n*m的矩阵A,求A中的一个非空子矩阵,使这个子矩阵中的元素和最大。
其中,A的子矩阵指在A中行和列均连续的一块。
输入格式
输入的第一行包含两个整数n, m,分别表示矩阵A的行数和列数。
接下来n行,每行m个整数,表示矩阵A。
输出格式
输出一行,包含一个整数,表示A中最大的子矩阵中的元素和。
样例输入
3 3
-1 -4 3
3 4 -1
-5 -2 8
样例输出
10
题目大意:求连续行、列的子矩阵的最大元素和。由于行、列必须是连续的,所以可以先求出每一列前n行的和,然后再枚举一个 行的开始和结束就可以啦,然后再用最大字段和求出最大和。本质是将二维的转化为一维的。
#include <iostream> #include<bits/stdc++.h> using namespace std; long long dp[505][505]; int main() { long long n,m,i,j,k; cin>>n>>m; for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { cin>>dp[i][j]; dp[i][j]+=dp[i][j-1]; } } long long maxx=dp[1][1]; for(i=1;i<=m;i++) { for(j=i;j<=m;j++) { long long s=0; for(k=1;k<=n;k++) { s+=dp[k][j]-dp[k][i-1]; if(s>maxx) maxx=s; if(s<0) s=0; } } } cout<<maxx<<endl; return 0; }
3;1+2;1+1+1;
共有三种划分方法。
给出一个正整数,问有多少种划分方法。
数据规模和约定
n< =100
3
3
动态规划题
建立一个二维数组横行代表将一个数拆几份
竖行代表要拆分的数那么方案数=arr[n][k].
我们要简化状态对于每一种分法我把它分成两种情况
1.分法里至少有一个1 比如 5 = 1+2+2 5 = 1+1+3
2.分法里没有1 比如 5 = 3+2
所以方案数=没有1的所有分法+有1的所有分法
#include <iostream> #include<bits/stdc++.h> using namespace std; int vis[101][101]; int f(int m,int i) { if(vis[m][i]) return vis[m][i]; if(m==i||i==1) return 1; if(i>m) return 0; return vis[m][i]=f(m-1,i-1)+f(m-i,i); } int main() { int n; cin>>n; long long sum=0; for(int i=1;i<=n;i++) { sum+=f(n,i); } cout<<sum<<endl; return 0; }
试编程计算,一共有多少种不同的摆花方案。
样例说明
有2种摆花的方案,分别是(1,1,1,2), (1,1,2,2)。括号里的1和2表示两种花,比如第一个方案是前三个位置摆第一种花,第四个位置摆第二种花。数据规模和约定
对于100%数据,有0< n≤100,0< m≤100,0≤ ai≤100。
第二行有n个整数,每两个整数之间用一个空格隔开,依次表示a1、a2、……an。
2 4 3 2
2
#include <iostream> #include<bits/stdc++.h> using namespace std; #define mod 1000007 int a[505][105],f[105]; int main() { int n,m; cin>>n>>m; int i,j; for(i=1;i<=n;i++) { cin>>f[i]; } a[0][0]=1; for(i=1;i<=n;i++) { for(j=0;j<=m;j++)//摆放的总盆数 { for(int h=0;h<=min(j,f[i]);h++)//第i种花摆放k盆 { a[i][j]=(a[i][j]+a[i-1][j-h])%mod; } } } cout<<a[n][m]<<endl; return 0; }