您的位置:首页 > 其它

剪格子(蓝桥)

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>, 不能通过工程设置而省略常用头文件。

提交时,注意选择所期望的编译器类型。

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: