蓝桥杯第五届第9题

标题:地宫取宝


    X 国王有一个地宫宝库。是 n x m 个格子的矩阵。每个格子放一件宝贝。每个宝贝贴着价值标签。


    地宫的入口在左上角,出口在右下角。


    小明被带到地宫的入口,国王要求他只能向右或向下行走。


    走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。


    当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可以送给小明。


    请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝。


【数据格式】


    输入一行3个整数,用空格分开:n m k (1<=n,m<=50, 1<=k<=12)


    接下来有 n 行数据,每行有 m 个整数 Ci (0<=Ci<=12)代表这个格子上的宝物的价值


    要求输出一个整数,表示正好取k个宝贝的行动方案数。该数字可能很大,输出它对 1000000007 取模的结果。


例如,输入:
2 2 2
1 2
2 1
程序应该输出:
2


再例如,输入:
2 3 2
1 2 3
2 1 5
程序应该输出:
14




资源约定:
峰值内存消耗 < 256M
CPU消耗  < 1000ms

#include<stdio.h>
#define N 50
#define M 50
#define MaxSize 5000
typedef struct
{
	int i,j;
	int kk;//物品数量 
	int max;//最大的 
}Box;
typedef struct
{
	Box data[MaxSize];
	int top;
}SqTack;//经典迷宫问题的结构体 
SqTack sq;
int mg[N][M],num[50]={0},n,m,k,c=0,ys=1000000007;
void push(int i,int j,int kk,int max)//进栈 
{
	sq.top++;
	sq.data[sq.top].i=i;
	sq.data[sq.top].j=j;
	sq.data[sq.top].kk=kk;
	sq.data[sq.top].max=max;
}
int xdfa(int s)//用数组保存数 
{
	int i=0;
	num[0]++;
	while(i<=s)
	{
		if(num[i]>9)
		{
			num[i+1]+=num[i]/10;
			num[i]=num[i]%10;
		}
		i++;
	}
	if(num[i]!=0)
	return i;
	else
	return i-1;
}
int decre(int cc)//大数作减法 
{
	int ysz[10]={7,0,0,0,0,0,0,0,0,1},i;
	for(i=0;i<cc;i++)
	{
		if(i<10)
		num[i]=num[i]-ysz[i];
		if(num[i]<0)
		{
			num[i]=10+num[i];
			num[i+1]--;
		}
	}
	if(num[cc]==0)
	return cc-1;
	else
	return cc;
}
int toInt(int cc)//数组转为整数 
{
	int m=0;
	while(cc>=0)
	{
		m=m*10+num[cc];
		cc--;
	}
	return m;
}
void print(int cc)//cc表示的是数组最高位,cc+1表示的是数组中的有效位数 
{
	while(cc>9)
	cc=decre(cc);
	printf("%d\n",toInt(cc)%ys);
}
void quBao(int xi,int yi,int xe,int ye)
{
	int i,j,max,kk=0,flag=0;
	sq.top=-1;
	sq.top++;
	sq.data[sq.top].i=i=xi;
	sq.data[sq.top].j=j=yi;
	sq.data[sq.top].kk=0;
	sq.data[sq.top].max=0;
	max=mg[i][j];
	kk++;
	while(flag==0)
	{
		flag=1;
		if(i==xe&&j==ye&&kk==k)
		{
			c=xdfa(c);
		}
		if(i==xe&&j==ye&&sq.top>-1)
		{
			i=sq.data[sq.top].i;
			j=sq.data[sq.top].j;
			max=sq.data[sq.top].max;
			kk=sq.data[sq.top].kk;
			sq.top--;
			flag=0;
		}
		if(i+1<n&&j+1<m)
		{
			if(mg[i+1][j]>max)
			{
				push(i+1,j,kk,max);
				push(i+1,j,kk+1,mg[i+1][j]);
			}
			else
			push(i+1,j,kk,max);
			if(mg[i][j+1]>max)
			push(i,j+1,kk+1,mg[i][j+1]);
			j=j+1;
			flag=0;
		}
		else if(i+1<n)
		{
			if(mg[i+1][j]>max)
			push(i+1,j,kk+1,mg[i+1][j]);
			i=i+1;
			flag=0;
		}
		else if(j+1<m)
		{
			if(mg[i][j+1]>max)
			push(i,j+1,kk+1,mg[i][j+1]);
			j=j+1;
			flag=0;
		}
	}
}
int main()
{
	int i,j;
	scanf("%d%d%d",&n,&m,&k);
	for(i=0;i<n;i++)
	for(j=0;j<m;j++)
	scanf("%d",&mg[i][j]);
	quBao(0,0,n-1,m-1);
	print(c);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值