hdu1876

机器人系列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.只有当机器人消耗完能量时才能获得相应格子上的能量。
请问机器人到达终点的过程中最多有几次完全消耗完能量,消耗完这么多次能量的方式有几种。
 

 

Input
输入
第一行输入一个整数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 3
1 2 3
3 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值