ZOJ Monthly, July 2012 - 补题 - zoj 3628 - Treasure Hunt III

当时比赛时候写了8题后时间不多了,就没继续做下去,不过看了下G题差不多知道怎么做了,不过感觉写起来麻烦。

今天早上写了下,果然写的挺麻烦的,至少看起来是。

因为有个循环,所以处理起来多要注意下s点上取不取值,以至于扫回来后,碰到s-1(或s+1,根据方向而定,扫到的最后一个点)点方便更新。

大致思路:和H题一样,最多一个方向上面只走一次,就是说转弯最多转一次。

dp[i][j][k]  前i秒,当前位置状态j(0,1)取不取值,s点状态(0,1),的最大值。

正反扫一次,就可以了。

代码看起来挺长的,其实一半都是复制粘贴。。。因为正反扫么。

View Code
  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<climits>
  6 #include<cstdlib>
  7 #include<queue>
  8 using namespace std;
  9 typedef long long LL;
 10 #define N 50010
 11 #define M 9910
 12 #define inf 1000000000
 13 LL val[N], dp1[N][2][2], dp2[N][2][2];
 14 int main() {
 15     int n, t, s;
 16     while (scanf("%d%d%d", &n, &t, &s) != EOF) {
 17         int lmax = min(t, n-1);
 18         for (int i = 1; i <= n; ++i)
 19             scanf("%lld", &val[i]);
 20         if (n == 1) {
 21             printf("%lld\n",val[1]);
 22             continue;
 23         }
 24         memset(dp1, -1, sizeof(dp1));
 25         dp1[0][0][0] = 0;
 26         dp1[0][1][1] = val[s];
 27         int id = s+1;
 28         for (int i = 1; i <= t; ++i, ++id) {
 29             if (id == n+1) id -= n;
 30             if (id == s) break;
 31             for (int j = 0; j < 2; ++j) {
 32                 if (id+1 == s || id == n && s == 1) {
 33                     if (dp1[i-1][0][j] != -1) {
 34                         dp1[i][0][j] = dp1[i-1][0][j];
 35                         if (!j) dp1[i][1][j] = dp1[i-1][0][j] + val[id];
 36                     }
 37                     if (dp1[i-1][1][j] != -1) 
 38                         dp1[i][0][j] = max(dp1[i][0][j], dp1[i-1][1][j]);
 39                     continue;
 40                 }
 41                 if (dp1[i-1][0][j] != -1) {
 42                     dp1[i][0][j] = dp1[i-1][0][j];
 43                     dp1[i][1][j] = dp1[i-1][0][j] + val[id];
 44                 }
 45                 if (dp1[i-1][1][j] != -1) 
 46                     dp1[i][0][j] = max(dp1[i][0][j], dp1[i-1][1][j]);
 47             }
 48         }
 49         LL ans = 0;
 50 
 51 
 52         memset(dp2, -1, sizeof(dp2));
 53         dp2[0][0][0] = 0;
 54         dp2[0][1][1] = val[s];
 55         id = s-1;
 56         for (int i = 1; i <= t; ++i, --id) {
 57             if (id == 0) id += n;
 58             if (id == s) break;
 59             for (int j = 0; j < 2; ++j) {
 60                 if (id-1 == s || id == 1 && s == n) {
 61                     if (dp2[i-1][0][j] != -1) {
 62                         dp2[i][0][j] = dp2[i-1][0][j];
 63                         if (!j) dp2[i][1][j] = dp2[i-1][0][j] + val[id];
 64                     }
 65                     if (dp2[i-1][1][j] != -1) 
 66                         dp2[i][0][j] = max(dp2[i][0][j], dp2[i-1][1][j]);
 67                     continue;
 68                 }
 69                 if (dp2[i-1][0][j] != -1) {
 70                     dp2[i][0][j] = dp2[i-1][0][j];
 71                     dp2[i][1][j] = dp2[i-1][0][j] + val[id];
 72                 }
 73                 if (dp2[i-1][1][j] != -1) 
 74                     dp2[i][0][j] = max(dp2[i][0][j], dp2[i-1][1][j]);
 75             }
 76         }
 77         for (int i = 0; i < 2; ++i) for (int j = 0; j < 2; ++j)
 78             ans = max(ans, max(dp2[lmax][i][j], dp1[lmax][i][j]));
 79 
 80         id = s;
 81         for (int i = 0; i <= t; ++i, ++id) {
 82             if (id == n+1) id -= n;
 83             if (id == s && i) break;
 84             int d = t-i*2;
 85             d = min(n-i-1, d);
 86             if (d > 0 && d+i+1 != n) {
 87                 for (int j = 0; j < 2; ++j) for (int k = 0; k < 2; ++k) {
 88                     LL t;
 89                     t = max(dp2[d][0][k], dp2[d][1][k]);
 90                     if (k && t != -1) t-= val[s];
 91                     if (t != -1) ans = max(ans, dp1[i][j][k] + t);
 92                 }
 93             }
 94         }
 95 
 96         id = s;
 97         for (int i = 0; i <= t; ++i, --id) {
 98             if (id == 0) id += n;
 99             if (id == s && i) break;
100             int d = t-i*2;
101             d = min(n-i-1, d);
102             if (d > 0 && d+i+1 != n) {
103                 for (int j = 0; j < 2; ++j) for (int k = 0; k < 2; ++k) {
104                     LL t;
105                     t = max(dp1[d][0][k], dp1[d][1][k]);
106                     if (k && t != -1) t -= val[s];
107                     if (t != -1) ans = max(ans, dp2[i][j][k] + t);
108                 }
109             }
110         }
111         printf("%lld\n", ans);
112     }
113     return 0;
114 }

转载于:https://www.cnblogs.com/slon/archive/2012/07/30/2614869.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值