剪格子(蓝桥)
2014-03-19 19:03
141 查看
如图p1.jpg所示,3 x 3 的格子中填写了一些整数。
我们沿着图中的红色线剪开,得到两个部分,每个部分的数字和都是60。
本题的要求就是请你编程判定:对给定的m x n 的格子中的整数,是否可以分割为两个部分,使得这两个区域的数字和相等。
如果存在多种解答,请输出包含左上角格子的那个区域包含的格子的最小数目。
如果无法分割,则输出 0
程序输入输出格式要求:
程序先读入两个整数 m n 用空格分割 (m,n<10)
表示表格的宽度和高度
接下来是n行,每行m个正整数,用空格分开。每个整数不大于10000
程序输出:在所有解中,包含左上角的分割区可能包含的最小的格子数目。
例如:
用户输入:
3 3
10 1 52
20 30 1
1 2 3
则程序输出:
3
再例如:
用户输入:
4 3
1 1 1 1
1 30 80 2
1 1 1 100
则程序输出:
10
(参见p2.jpg)
资源约定:
峰值内存消耗 < 64M
CPU消耗 < 5000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。
提交时,注意选择所期望的编译器类型。
N久之后,2014年5月28日 19:05:35,来看这个感觉有问题,题目的意思是左上角的一块必须选择。
但是上面的算法是从左上角开始深搜的,所以这个的情况可能会找不出答案:
这个答案应该是 选择1 2 3 。
所有dfs应该每个点都要作为起点尝试(应该有更简单的,这里没有深入),在递归加入条件限制当搜索出结果之后,如果左上角没有选取,则丢弃当前结果。
我测试是用一个向量保存所有满足的情况,并打印。
当测试数据是上面的情况时候,打印的路径:
也就是选取1 2 3 这一块
当测试数据是:
当然这是有重复的。
这样就能选出所有符合条件的情况。
但是,还有一个问题。
题目的意思是分割成两部分,
这些情况有分割成3部分或者多部分的情况,
这个我还没想到方法,这样的情况比较少了吧。
贴上在蓝桥练习系统的代码,测评是100分。
这题就算是ac了吧。看看以前写的这题,好多都没用考虑,只是单纯的知道方法,而没有灵活应用,没有考虑到很多情况。
这题时隔那么久再做,有种豁然开朗的感觉。
最后贴一下dfs自己分析时候的图和代码,还是为了方便自己以后再看这题。
-代表递归的层次
数据是:
2 2
1 2
3 6
分析的代码(不是提交oj的代码,提交oj的代码在上面):
我们沿着图中的红色线剪开,得到两个部分,每个部分的数字和都是60。
本题的要求就是请你编程判定:对给定的m x n 的格子中的整数,是否可以分割为两个部分,使得这两个区域的数字和相等。
如果存在多种解答,请输出包含左上角格子的那个区域包含的格子的最小数目。
如果无法分割,则输出 0
程序输入输出格式要求:
程序先读入两个整数 m n 用空格分割 (m,n<10)
表示表格的宽度和高度
接下来是n行,每行m个正整数,用空格分开。每个整数不大于10000
程序输出:在所有解中,包含左上角的分割区可能包含的最小的格子数目。
例如:
用户输入:
3 3
10 1 52
20 30 1
1 2 3
则程序输出:
3
再例如:
用户输入:
4 3
1 1 1 1
1 30 80 2
1 1 1 100
则程序输出:
10
(参见p2.jpg)
资源约定:
峰值内存消耗 < 64M
CPU消耗 < 5000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。
提交时,注意选择所期望的编译器类型。
#include <iostream> using namespace std; int data[12][12],sum,ans,m,n; int vi[4]={1,-1,0,0}; int vj[4]={0,0,1,-1}; int flag[12][12]; const int INF=999999; void dfs(int i,int j,int count,int s) { if(s+s>sum) return; if(count>ans) return; if(s+s==sum) { ans=count<ans?count:ans; return; } flag[i][j]=1; int k,nexti,nextj; for(k=0;k<4;k++) { nexti=i+vi[k]; nextj=j+vj[k]; if(nexti<1||nexti>m||nextj<1||nextj>n||flag[nexti][nextj]==1) continue ; dfs(nexti,nextj,count+1,s+data[nexti][nextj]); } flag[i][j]=0; } int main() { int i,j; // freopen("data.txt","r",stdin); while(cin>>n>>m) { sum=0; ans=INF; for(i=1;i<=m;i++) for(j=1;j<=n;j++) { cin>>data[i][j]; sum+=data[i][j]; flag[i][j]=0; } if(sum%2) { cout<<0<<endl; continue; } if(data[1][1]*2==sum) { cout<<1<<endl; } dfs(1,1,1,data[1][1]); if(ans*2>m*n) ans=n*m-ans; if(ans==INF) ans=0; cout<<ans<<endl; } // system("pause"); return 0; }
N久之后,2014年5月28日 19:05:35,来看这个感觉有问题,题目的意思是左上角的一块必须选择。
但是上面的算法是从左上角开始深搜的,所以这个的情况可能会找不出答案:
2 2 1 2 3 6
这个答案应该是 选择1 2 3 。
所有dfs应该每个点都要作为起点尝试(应该有更简单的,这里没有深入),在递归加入条件限制当搜索出结果之后,如果左上角没有选取,则丢弃当前结果。
我测试是用一个向量保存所有满足的情况,并打印。
当测试数据是上面的情况时候,打印的路径:
也就是选取1 2 3 这一块
当测试数据是:
4 3 1 2 3 4 10 30 25 5 9 8 7 6
当然这是有重复的。
这样就能选出所有符合条件的情况。
但是,还有一个问题。
题目的意思是分割成两部分,
这些情况有分割成3部分或者多部分的情况,
这个我还没想到方法,这样的情况比较少了吧。
贴上在蓝桥练习系统的代码,测评是100分。
这题就算是ac了吧。看看以前写的这题,好多都没用考虑,只是单纯的知道方法,而没有灵活应用,没有考虑到很多情况。
这题时隔那么久再做,有种豁然开朗的感觉。
#include <iostream> #include <vector> using namespace std; const int INF=99999999; int data[12][12],flag[12][12],m,n; int ans=INF,KEY=0; int fx[4][2]={{0,-1},{0,1},{1,0},{-1,0}}; vector <int> v; void dfs(int i,int j,int re,int count){ if(flag[i][j]==1||i<1||i>n||j<1||j>m||re>KEY){ return; } if(re==KEY){ if(flag[1][1]==0){//左上角必须选择 return; } if(ans>count) ans=count; // for(int i=0;i<v.size();i++){ // cout<<v[i]<<" "; // } // cout<<endl; return; } // cout<<i<<","<<j<<":"<<data[i][j]<<",re:"<<re+data[i][j]<<endl; int k; for(k=0;k<4;k++){ flag[i][j]=1; v.push_back(data[i][j]); dfs(i+fx[k][0],j+fx[k][1],re+data[i][j],count+1); flag[i][j]=0; v.erase(v.end()-1); } } int main(){ // freopen("data.txt","r",stdin); cin>>m>>n; int i,j; for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ cin>>data[i][j]; flag[i][j]=0; KEY+=data[i][j]; } } if(KEY%2){ cout<<0<<endl; return 0; } KEY=KEY/2; for(i=1;i<=n;i++) for(j=1;j<=m;j++) dfs(i,j,0,0); cout<<ans<<endl; return 0; }
最后贴一下dfs自己分析时候的图和代码,还是为了方便自己以后再看这题。
-代表递归的层次
数据是:
2 2
1 2
3 6
分析的代码(不是提交oj的代码,提交oj的代码在上面):
#include <iostream> #include <vector> using namespace std; const int INF=99999999; int data[12][12],flag[12][12],m,n; int ans=INF,KEY=0; int fx[4][2]={{0,-1},{0,1},{1,0},{-1,0}}; vector <int> v; void dfs(int i,int j,int re,int count){ if(flag[i][j]==1||i<1||i>n||j<1||j>m||re>KEY){ return; } if(re==KEY){ if(flag[1][1]==0){//左上角必须选择 return; } if(ans>count) ans=count; // for(int i=0;i<v.size();i++){ // cout<<v[i]<<" "; // } // cout<<endl; cout<<" ok!"; return; } cout<<endl; for(int k=0;k<count;k++) cout<<"-"; cout<<i<<","<<j<<":"<<data[i][j]<<",re:"<<re+data[i][j]; int k; for(k=0;k<4;k++){ flag[i][j]=1; v.push_back(data[i][j]); dfs(i+fx[k][0],j+fx[k][1],re+data[i][j],count+1); flag[i][j]=0; v.erase(v.end()-1); } } int main(){ freopen("data.txt","r",stdin); cin>>m>>n; int i,j; for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ cin>>data[i][j]; flag[i][j]=0; KEY+=data[i][j]; } } if(KEY%2){ cout<<0<<endl; return 0; } KEY=KEY/2; for(i=1;i<=n;i++) for(j=1;j<=m;j++) dfs(i,j,0,0); cout<<endl<<"ans:"<<ans<<endl; return 0; }
相关文章推荐
- 【蓝桥训练】历届试题 剪格子
- 蓝桥 操作格子 线段树 单点更新 区间查询
- 蓝桥 2×3格子移字母 (bfs)
- 蓝桥- 历届试题 2013-10-19剪格子 搜索
- 蓝桥 格子中输出
- 【蓝桥】历届试题 剪格子
- 蓝桥-ALGO-8 操作格子
- [ZT][精]格子经济
- Simon的新中文“百万格子”重磅推出
- 忆龙2009:OPENGL 我的格子到哪里去了
- SU/Demos/CShot /~~一点说明 转自(格子的研发基地 )
- UESTC 1686——跳格子
- 扫雷程序完美版!!!!!!可以通过点击鼠标来翻开格子或者做上标记 !!!!!!!
- 火柴游戏 这是一个纵横火柴棒游戏。如图[1.jpg],在3x4的格子中,游戏的双方轮流放置火柴棒。
- 格子布局 js
- 程序员编程艺术第三十四~三十五章:格子取数问题,完美洗牌算法
- 第四届蓝桥杯--剪格子
- 翻格子游戏
- 算法训练 操作格子
- 一次格子取数的问题