您的位置:首页 > 其它

2014蓝桥杯 地宫取宝 &&hdu 4597 四维数组状态记忆化

2016-03-18 23:21 831 查看
地宫取宝

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

请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。

注意: main函数需要返回0

注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。

注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。

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

本题是一个状态推移的dfs题目,但需要设置数组d[][][][]进行记忆化搜索节省时间。但是本题有个巨大的陷阱,一开始忽略了,调试了很长时间总是不成功只对前两个测试用例,原来是一开始dfs(1,1,0,-1)一开始价值要为-1才行,因为图中map[][]可以为0,下面是我的AC代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int map[60][60];
int n,m,k;
int d[55][55][20][20];
int dfs(int x,int y,int num,int w)
{
if(d[x][y][num][w+1]!=-1)
return d[x][y][num][w+1];
if(x==n&&y==m)
{
if(num==k||num==k-1&&map[x][y]>w)
d[x][y][num][w+1]=1;
else
d[x][y][num][w+1]=0;
return d[x][y][num][w+1];
}
if(num>k)
return 0;
int t=0;
if(y<m)
{
if(map[x][y]>w)
{
t+=dfs(x,y+1,num+1,map[x][y]);
t=t%1000000007;
t+=dfs(x,y+1,num,w);
t=t%1000000007;
}
else
{
t+=dfs(x,y+1,num,w);
t=t%1000000007;
}
}
if(x<n)
{
if(map[x][y]>w)
{
t+=dfs(x+1,y,num+1,map[x][y]);
t=t%1000000007;
t+=dfs(x+1,y,num,w);
t=t%1000000007;
}
else
{
t+=dfs(x+1,y,num,w);
t=t%1000000007;
}
}
d[x][y][num][w+1]=t;
return d[x][y][num][w+1];
}
int main()
{
memset(d,-1,sizeof(d));
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>map[i][j];
d[1][1][0][0]=dfs(1,1,0,-1);
cout<<d[1][1][0][0]<<endl;
return 0;
}


Problem Description

Alice and Bob are playing a game. There are two piles of cards. There are N cards in each pile, and each card has a score. They take turns to pick up the top or bottom card from either pile, and the score of the card will be added to his total score. Alice
and Bob are both clever enough, and will pick up cards to get as many scores as possible. Do you know how many scores can Alice get if he picks up first?

Input

The first line contains an integer T (T≤100), indicating the number of cases.

Each case contains 3 lines. The first line is the N (N≤20). The second line contains N integer ai (1≤ai≤10000). The third line contains N integer bi (1≤bi≤10000).

Output

For each case, output an integer, indicating the most score Alice can get.

Sample Input

2

1
23
53

3
10 100 20
2 4 3


Sample Output

53
105


dp[la][ra][lb][rb]记录的是在a的区间为la~ra,b的区间为lb~rb的情况下,某人采取最好策略的总分数

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define LL long long
using namespace std;
int n;
int a[30],b[30];
int d[30][30][30][30];
int dfs(int al,int ar,int bl,int br,int sum)
{
if(d[al][ar][bl][br]!=-1)
return d[al][ar][bl][br];
if(ar<al&&br<bl)//必须是&&
return 0;
int maxx=0;
if(al<=ar)
{
maxx=max(maxx,sum-dfs(al+1,ar,bl,br,sum-a[al]));
maxx=max(maxx,sum-dfs(al,ar-1,bl,br,sum-a[ar]));
}
if(bl<=br)
{
maxx=max(maxx,sum-dfs(al,ar,bl+1,br,sum-b[bl]));
maxx=max(maxx,sum-dfs(al,ar,bl,br-1,sum-b[br]));
}
return d[al][ar][bl][br]=maxx;
}
int main()
{
int T;
cin>>T;
while(T--)
{
int sum=0;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum+=a[i];
}
for(int j=1;j<=n;j++)
{
cin>>b[j];
sum+=b[j];
}
memset(d,-1,sizeof(d));
cout<<dfs(1,n,1,n,sum)<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: