Tyvj P3276

题目链接:http://www.tyvj.cn/p/3276

这题是一个动归题,一直没有想出动归的做法,后来求教别人之后写了一个记忆化搜索,只有出题者又给我提供了DP的解法,下面我来写写DP的写法

设置数组dp[i][j],表示从位置j开始,后面i个数的最大值

去掉最右端的数:dp[i][j]=sum[i+j-2]-sum[j-1]-dp[i-1][j]+a[i+j-1]

去掉最左端的数:dp[i][j]=sum[i+j-1]-sum[j]-dp[i-1][j+1]+a[j]

(具体参看笔记)

然后再取左边和右边的最大值即可,很好的题目,确实值得一做

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<cmath>
 6 #include<vector>
 7 #include<algorithm>
 8 #include<map>
 9 using namespace std;
10 const int maxn=1000+10;
11 int a[maxn],sum[maxn];
12 int dp[maxn][maxn];
13 int main()
14 {
15     int n;
16     while(cin>>n)
17     {
18         memset(dp,0,sizeof(dp));
19         memset(sum,0,sizeof(sum));
20         for(int i=1;i<=n;i++)
21         {
22             cin>>a[i];
23             sum[i]=sum[i-1]+a[i];
24         }
25         for(int i=1;i<=n;i++)
26             dp[1][i]=a[i];
27         for(int i=2;i<=n;i++)
28             for(int j=1;j<=n-i+1;j++)
29         {
30             dp[i][j]=sum[i+j-2]-sum[j-1]-dp[i-1][j]+a[i+j-1];  //去掉最右端的数
31             if(dp[i][j]<sum[i+j-1]-sum[j]-dp[i-1][j+1]+a[j])
32                 dp[i][j]=sum[i+j-1]-sum[j]-dp[i-1][j+1]+a[j];  //去掉最左端的数
33         }
34         cout<<dp[n][1]<<" "<<sum[n]-dp[n][1]<<endl;
35     }
36     return 0;
37 }

同时,我也把别人写的记忆化搜索的代码贴上去

Query(l, r),表示当前先手在l-r能取到的最大分数,这个分数可能是取左边的得来的,也可能是取右边的得来的,

所以是它们的max,如果取的是左边,那么最后的分数是左边的分数,加上(剩下的和减去对方能取到的最大结果)

 1 #include <stack>
 2 #include <cstdio>
 3 #include <list>
 4 #include <cassert>
 5 #include <set>
 6 #include <iostream>
 7 #include <string>
 8 #include <vector>
 9 #include <queue>
10 #include <functional>
11 #include <cstring>
12 #include <algorithm>
13 #include <cctype>
14 #include <string>
15 #include <map>
16 #include <cmath>
17 #include <ext/pb_ds/assoc_container.hpp>
18 #include <ext/pb_ds/hash_policy.hpp>
19 using namespace std;
20 #define LL long long
21 #define ULL unsigned long long
22 #define SZ(x) (int)x.size()
23 #define Lowbit(x) ((x) & (-x))
24 #define MP(a, b) make_pair(a, b)
25 #define MS(arr, num) memset(arr, num, sizeof(arr))
26 #define PB push_back
27 #define X first
28 #define Y second
29 #define ROP freopen("input.txt", "r", stdin);
30 #define MID(a, b) (a + ((b - a) >> 1))
31 #define LC rt << 1, l, mid
32 #define RC rt << 1|1, mid + 1, r
33 #define LRT rt << 1
34 #define RRT rt << 1|1
35 const double PI = acos(-1.0);
36 const int INF = 0x3f3f3f3f;
37 const double eps = 1e-8;
38 const int MAXN = 5e4+10;
39 const int MOD = 9901;
40 const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
41 int cases = 0;
42 typedef pair<int, int> pii;
43
44 int arr[300], sum[300];
45 map<pii, int> mp;
46
47 int Query(int l, int r)
48 {
49     if (mp.count(MP(l, r))) return mp[MP(l, r)];
50     if (l == r) return arr[l];
51     int ans;
52     ans = max(arr[l] + sum[r]-sum[l]-Query(l+1, r), arr[r] + sum[r-1]-sum[l-1]-Query(l, r-1));
53     mp[MP(l, r)] = ans;
54     return ans;
55 }
56
57 int main()
58 {
59     //ROP;
60     int n;
61     scanf("%d", &n);
62     for (int i = 1; i <= n; i++)
63     {
64         scanf("%d", &arr[i]);
65         sum[i] = arr[i];
66         sum[i] += sum[i-1];
67     }
68     int ans = Query(1, n);
69     printf("%d %d\n", ans, sum[n]-ans);
70     return 0;
71 }
72
73
74 Download as text 

感悟就是我太弱了,已经不能忍,接下来无论是考研,还是创新项目,抑或是刷题,都必须好好努力了

时间: 2024-10-10 00:46:06

Tyvj P3276的相关文章

TYVJ 2049 魔法珠 sg函数

题意:链接 方法:sg函数 解析: tyvj的题大部分都没题解啊- - 不过这样貌似会更好?感觉做这的题都需要自己动脑啊- - 虽然嘴上说着好烦然而心里觉得好评? 回归正题 设sg[x]表示数x的sg值,这好像是废话 然后对于读入的a[i],将所有的a[i]的sg值异或起来如果不是零则先手赢反之后手 维护的时候有个坑. 每次求约数的时候,数组要在sg里开,因为如果递归下去的话,全局变量的话会被更改,会被坑死. 然后就是怎么维护了 对于x,先求约数 之后枚举哪个数不取,将其他的异或(或者先都异或起

bzoj 3224: Tyvj 1728 普通平衡树.

3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 15114  Solved: 6570[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为

Bzoj3196 Tyvj 1730 二逼平衡树

Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3350  Solved: 1324 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查询k在区间内的后继(后继定义为大于x,且最小的数) Input 第一行两个数 n,m 表示长度为n的有序序列和m个操作第二行

3223: Tyvj 1729 文艺平衡树

3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3473  Solved: 1962[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 Input 第一行为n,m n表示初始序列有n个数,这个序列依次

【bfs】【中等难度】tyvj P1234 - bench与奔驰

P1234 - bench与奔驰 From zhangbh001    Normal (OI) 总时限:10s    内存限制:128MB    代码长度 限制:64KB P1234 - bench与奔驰 背景 Background 公园里有个人在练开奔驰 - -!,但是总是撞在bench上 (众人曰:狼来了,快跑啊!) 描述 Description 公园里的bench与奔驰都是无敌的,不会被撞坏.由于开奔驰的人比较"有特点",总是向上下左右四个方向开,而且只会在撞到椅子之后改变方向(

tyvj p1016 装箱问题

装箱问题From admin 描述 Description 有一个箱子容量为v(正整数,o≤v≤20000),同时有n个物品(o≤n≤30), 每个物品有一个体积 (正整数). 要求从 n 个物品中,任取若干个装入箱内,使箱子的剩余空间为最小. 输入格式 InputFormat第一行,一个整数,表示箱子容量:第二行,一个整数,表示有n个物品:接下来n行,分别表示这n个物品的各自体积.输出格式 OutputFormat一个整数,表示箱子剩余空间. 简单DP 01背包 #include<stdio.

BZOJ 3223: Tyvj 1729 文艺平衡树

3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3629  Solved: 2053[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 Input 第一行为n,m n表示初始序列有n个数,这个序列依次

BZOJ3224: Tyvj 1728 普通平衡树[treap]

3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 9046  Solved: 3840[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为小

Tyvj 1176 火焰巨魔的惆怅

Tyvj 1176 火焰巨魔的惆怅 背景 TYVJ2月月赛第一道 巨魔家族在某天受到了其他种族的屠杀,作为一个英雄,他主动担任了断后的任务,但是,在巨魔家族整体转移过后,火焰巨魔却被困住了,他出逃的方式也只有召唤小火人这一种方式,所以请你帮助他. 描述 我们把火焰巨魔所处的位置抽象成一张有向图,他的位置就是1号点位,目的就是走到第N号点位,因为小火人会裂嘛,所以我们可以看做每走一条路,小火人的数量都会加倍,而每条路上的敌人有多强,会消耗多少小火人c[i]也会给出(c[i]为负值):当然有些时候路