描述
鲁宾逊先生有一只宠物猴,名叫多多。这天,他们两个正沿着乡间小路散步,突然发现路边的告示牌上贴着一张小小的纸条:“欢迎免费品尝我种的花生!——熊字”。
鲁宾逊先生和多多都很开心,因为花生正是他们的最爱。在告示牌背后,路边真的有一块花生田,花生植株整齐地排列成矩形网格(如图1)。有经验的多多一眼就能看出,每棵花生植株下的花生有多少。为了训练多多的算术,鲁宾逊先生说:“你先找出花生最多的植株,去采摘它的花生;然后再找出剩下的植株里花生最多的,去采摘它的花生;依此类推,不过你一定要在我限定的时间内回到路边。”
我们假定多多在每个单位时间内,可以做下列四件事情中的一件:
1) 从路边跳到最靠近路边(即第一行)的某棵花生植株;
2) 从一棵植株跳到前后左右与之相邻的另一棵植株;
3) 采摘一棵植株下的花生;
4) 从最靠近路边(即第一行)的某棵花生植株跳回路边。
现在给定一块花生田的大小和花生的分布,请问在限定时间内,多多最多可以采到多少个花生?注意可能只有部分植株下面长有花生,假设这些植株下的花生个数各不相同。
例如在图2所示的花生田里,只有位于(2, 5), (3, 7), (4, 2), (5, 4)的植株下长有花生,个数分别为13, 7, 15, 9。沿着图示的路线,多多在21个单位时间内,最多可以采到37个花生。输入
输入的第一行包括一个整数T,表示数据组数
每组输入的第一行包括三个整数,M, N和K,用空格隔开;表示花生田的大小为M * N(1 <= M, N <= 50),多多采花生的限定时间为K(0 <= K <= 1000)个单位时间。接下来的M行,每行包括N个非负整数,也用空格隔开;第i + 1行的第j个整数Pij(0 <= Pij <= 500)表示花生田里植株(i, j)下花生的数目,0表示该植株下没有花生。输出
输出包括T行,每一行只包含一个整数,即在限定时间内,多多最多可以采到花生的个数。
样例输入
2 6 7 21 0 0 0 0 0 0 0 0 0 0 0 13 0 0 0 0 0 0 0 0 7 0 15 0 0 0 0 0 0 0 0 9 0 0 0 0 0 0 0 0 0 0 6 7 20 0 0 0 0 0 0 0 0 0 0 0 13 0 0 0 0 0 0 0 0 7 0 15 0 0 0 0 0 0 0 0 9 0 0 0 0 0 0 0 0 0 0
样例输出
37 28
这个问题的测试数据有问题,建议查看POJ1928的英文问题。同时我找到了测试用例NOPI2004。找到了测试数据。代码比较啰嗦,完全按照模拟的方法来做的,中间因为死活不对还重新写了一遍程序。在这里不得不感叹OJ的严谨性。
我的第一个版本的程序在“如果可以采完所有的花生”这种情况是输出有问题,我把输出语句放在了for循环里,导致多输出了好几句。这给我敲响了警钟。
第二个版本的程序的BUG就更加隐蔽了。我在两个for循环的嵌套中,重置了i和j均为1,本来很方便的一件事,但是因为没有考虑到在for循环中的j++这一句代码。不错,j声明成了1,但是内层for循环紧接着就结束了,执行j++,j变成了2,这就导致了(1,1)这种情况被漏掉了。
放出来两个修改好的代码,思路都是一样的。完全按照题目的方法进行模拟。
一
#include<iostream>
#include<cmath>
#include<algorithm>
#include<stack>
using namespace std;
bool cmp(int a, int b)
{
return a > b;
}
stack<int>fin;
bool home(int hang, int time)
{
if (time >= hang)
{
return true;
}
else
{
return false;
}
}
int main()
{
int cishu; cin >> cishu;
int a, b, time, zhongliang;
bool zhongji;
while (cishu--)
{
zhongji = true;
int w = 0; int l = 0;
zhongliang = 0;
int arr[60][60];
int you[3600] = { 0 };
cin >> a >> b >> time;
for (int i = 1; i <= a; i++)
{
for (int j = 1; j <= b; j++)
{
cin >> l;
you[w++] = l;
arr[i][j] = l;
}
}
sort(you, you + 3500, cmp);
int lushu = 0;
int j = 1; int k = 1;
for (j = 1; j <= a; j++)
{
bool f = false;
for (k = 1; k <= b; k++)
{
if (you[0] == arr[j][k])
{
lushu = j + 1;
if (!home(j, time - lushu))
{
cout << 0 << endl;
zhongji = false;
break;
}
f = true;
break;
}
}
if (f)
{
break;
}
}
if (zhongji)
{
for (int m = 1; m < 3000; m++)
{
if (zhongji)
{
if (you[m] != 0)
{
for (int i = 1; i <= a; i++)
{
bool q = false;
for (int p = 1; p <= b; p++)
{
if (arr[i][p] == you[m])
{
lushu = lushu + abs(i - j) + abs(p - k) + 1;
j = i; k = p;
q = true;
if (!home(i, time - lushu))
{
for (int q = 0; q < m; q++)
{
zhongliang += you[q];
}
cout << zhongliang << endl;
zhongji = false;
break;
}
break;
}
}
if (q)
{
break;
}
}
}
else
{
for (int i = 0; i <= m; i++)
{
zhongliang += you[i];
zhongji = false;
}
cout << zhongliang << endl;
break;
}
}
}
}
}
system("pause");
}
二
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
bool huijia(int need,int times)
{
if(times<need)
{
return false;
}else{
return true;
}
}
bool compare(int a,int b)
{
return a>b;
}
int main()
{
int peanut[60][60]={0};
int T;
int M,N,K;
cin>>T;
while(T--) //组数
{
int Num[2600]={0};
bool zhongji=true;
int zhongliang=0;
int shurutishen=0;
int hang,lie;
cin>>M>>N>>K;
for(int i=1;i<=M;i++)
{
for(int j=1;j<=N;j++)
{
cin>>peanut[i][j];
Num[shurutishen++]=peanut[i][j];
}
}//完成了输入
sort(Num,Num+2600,compare);//完成了排序工作
//开始模拟
int NumofNum=0;
int xiaohao=0;
for(int i=1;i<=M;i++){
for(int j=1;j<=N;j++)
{
if(Num[0]==peanut[i][j])
{
xiaohao=i+1;
if(huijia(i,K-xiaohao))
{
NumofNum++;
hang=i;lie=j;
zhongliang+=Num[0];
}
else
{
zhongji=false;
cout<<0<<endl;
}
}
}
}
if (zhongji)
{
for(int i=1;i<=M;i++)
{
for(int j=1;j<=N;j++)
{
if(Num[NumofNum]!=0)
{
if(Num[NumofNum]==peanut[i][j])
{
xiaohao=xiaohao+1+abs(hang-i)+abs(lie-j);
if(huijia(i,K-xiaohao))
{
hang=i;lie=j;
zhongliang+=Num[NumofNum];
NumofNum++;
i=0;j=0;
}
else
{
cout<<zhongliang<<endl;
}
}
}
else
{
if(zhongji)
cout<<zhongliang<<endl;
zhongji=false;
}
}
}
}
}
}
个人推荐第二个,因为没有第一版那么凌乱。