NOIP 2007矩阵取数游戏 解题报告(区间型DP)

在线评测:

http://codevs.cn/problem/1166/

(为了便于书写,以下内容不含高精度,包括AC代码,(简洁,更易理解))

整体思路:

还是感觉记忆化搜索比较好写,就写了记忆化搜索。每次考虑一个区间,先去掉首元素和先去掉尾元素的情况。然后记忆化搜下去下去就好

预处理只要处理处每一个数最后被选的得分是多少即可

失误之处:

开始只用dpij是否为0判断这个区间有没有被搜过,但是后来发现,有些区间他本身就是0.。。你这么一直搜就re了,,,,,

后来改用vis。然而由于是多case,,,然后vis每次没初始化为0,,,就固定输出第一组,,,QAQ

对了,,还是那个傻逼错误,,调用dfs的时候又习惯性写成直接访问dp数组,,,,

别光想着把数组什么开成int64,,,dfs返回值也得开longlong,,,

体会心得:

平时应该复习一下高精度什么。。。

多case什么的多看看初始化的周不周到。。。。

别光想着把数组什么开成int64,,,dfs返回值也得开longlong,,,要全面。。

AC代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using  namespace  std;
int  n,m;
bool  vis[100][100];
long  long  ans,dp[100][100],sz[100];
long  long  ksm( int  x, int  k)
{
     if  (k == 1)  return  x;
     long  long  tp = ksm(x,k >> 1);
     if  (k & 1)  return  tp * tp * x;
     return  tp * tp;
}
long  long  dfs( int  s, int  t)
{
     if  (vis[s][t])  return  dp[s][t];
     vis[s][t] =  true ;
     return  dp[s][t] = max(dfs(s+1,t) + sz[s] * ksm(2,m - t + s), dfs(s,t - 1) + sz[t] * ksm(2,m - t + s));
}
void  init()
{
     memset (dp,0, sizeof (dp));
     memset (vis,0, sizeof (vis));
     for  ( int  i = 1;i <= m;i++)
         dp[i][i] = sz[i] * ksm(2,m),vis[i][i] =  true ;
}
int  main()
{
     scanf  ( "%d%d" ,&n,&m);
     for  ( int  i = 1;i <= n;i++)
     {
         for  ( int  j = 1;j <= m;j++)
         {
             scanf ( "%lld" ,&sz[j]);
         }
         init();
         long  long  tp = 0;
         tp = dfs(1,m);
         ans += tp;
     }
     printf ( "%lld\n" ,ans);
     return  0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值