机器人系列2
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 566 Accepted Submission(s): 96
Problem Description
这又是一个简单的游戏,你控制一个机器人从一个棋盘的起始点(1,1)走到棋盘的终点(n,m)。游戏的规则描述如下:
1.机器人一开始在棋盘的起始点(1,1)并有起始点所标有的能量。
2.机器人只能向右或者向下走,并且每走一步消耗一单位能量。
3.只有当机器人消耗完能量时才能获得相应格子上的能量。
请问机器人到达终点的过程中最多有几次完全消耗完能量,消耗完这么多次能量的方式有几种。
1.机器人一开始在棋盘的起始点(1,1)并有起始点所标有的能量。
2.机器人只能向右或者向下走,并且每走一步消耗一单位能量。
3.只有当机器人消耗完能量时才能获得相应格子上的能量。
请问机器人到达终点的过程中最多有几次完全消耗完能量,消耗完这么多次能量的方式有几种。
Input
输入
第一行输入一个整数T,表示数据的组数。
对于每一组数据第一行输入两个整数n,m(1 <= n,m <= 100)。表示棋盘的大小。接下来输入n行,每行m个整数e(0 <= e < 20)。
第一行输入一个整数T,表示数据的组数。
对于每一组数据第一行输入两个整数n,m(1 <= n,m <= 100)。表示棋盘的大小。接下来输入n行,每行m个整数e(0 <= e < 20)。
Output
请问机器人到达终点的过程中最多有几次完全消耗完能量,消耗完这么多次能量的方式有几种。
Sample Input
1 6 6 4 5 6 6 4 3 2 2 3 1 7 2 1 1 4 6 2 7 5 8 4 3 9 5 7 6 6 2 1 5 3 1 1 3 7 2
Sample Output
3 4这道题暂时还没解决,但感触较多,所以先写点东西上来,最恶心的是题目为说清统计次数是否包括最后一步,觉得很可能是次数统计把握不好,就是从底端开始计算时并未对实际消耗次数为零的次数进行统计,事实上这是需要统计的:譬如用例2 1 31 2 33 2 1输出结果为 1 3 并不是所要的答案一开始以为dp没法记录次数(不关心到达当前状态的步骤)决定用搜索算法,已经尽量减枝了,最后还是栈溢出代码还是拷在这儿://每一个点都有两种决策,显然是要回溯的,使用搜索算法,但这里结点很多,减枝就显得尤为重要,这里注意的是无论怎么走总的步数
//是不变的,能量值的总消耗不变,这是一个非常重要的信息,可能我们可以考虑贪心(考虑获取能量值最小)求数量应该选择搜索
#include <iostream>
using namespace std;
int map[103][103];
int maxcount;
int times;void find(int xpos,int ypos,int count,int n,int m)
{
//首先考虑在该结点获得能量值后能否到达终点
int value=map[xpos][ypos];
if(n+m-xpos-ypos<=value)
{
if(count>maxcount)maxcount=count,times=1;
else if(count==maxcount)times++;
}
for(int i=xpos;i<=xpos+value&&i<=n;i++)//搜索连续走value步之后可以到达的点
{
int j=xpos+ypos+value-i;
if(j<=m)find(i,j,count+1,n,m);
}
}
int main()
{
int t;
cin>>t;
int n,m;
while(t--)
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>map[i][j];maxcount=-1;
find(1,1,0,n,m);
cout<<maxcount<<" "<<times<<endl;
}
return 0;
}接下来问了一个搞acm的同学,用的是递推版本 还是WA:#include<iostream>
//#include<fstream>
using namespace std;
#define MAXN 120
int step[MAXN][MAXN];
int kind[MAXN][MAXN];
int map[MAXN][MAXN];
int n,m;//FILE *fin;void init()
{
int i,j;
scanf("%d%d",&n,&m);
// fscanf(fin,"%d%d",&n,&m);
for(i=0;i<n;i++)
{
for(j=0;j<m;j++) scanf("%d",&map[i][j]);
}
}void solve()
{
int i,j,d,nowx,nowy;
int ans_step,ans_kind;
memset(step,0,sizeof(step));
memset(kind,0,sizeof(kind));
kind[0][0] = 1;
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
if((kind[i][j]==0)) continue;
d = map[i][j];
nowx = i+d;
nowy = j;
if(nowx>=n)
{
nowy = nowy+nowx-(n-1);
nowx = n-1;
}
while(nowx>=i && nowy<m)
{
if(step[i][j]+1>step[nowx][nowy])
{
step[nowx][nowy] = step[i][j]+1;
kind[nowx][nowy] = kind[i][j];
}else
if(step[i][j]+1==step[nowx][nowy])
{
kind[nowx][nowy] += kind[i][j];
}
nowx--;
nowy++;
}
}
}
/* for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
printf("%d ",kind[i][j]);
}
printf("/n");
}
*/
ans_step = 0;
for(i=0;i<n;i++)
for(j=0;j<m;j++)
if(step[i][j]>ans_step) ans_step = step[i][j];ans_kind = 0;
for(i=0;i<n;i++)
for(j=0;j<m;j++)
if(step[i][j]==ans_step) ans_kind += kind[i][j];printf("%d %d/n",ans_step,ans_kind);
}int main()
{
int t;
// fin = fopen("hdu1876.in","r");
scanf("%d",&t);
// fscanf(fin,"%d",&t);
while(t--)
{
init();
solve();
}
return 0;
}