2012 2012 Multi-University Training Contest 7 Dragon Ball


如此简单的题目,让我们两个一直卡到最后也没搞出来,我的二分写惨了,他的游标也写错了。现在给出比较靠谱的写法,在下一层定位的时候,把上一层和下一层的合并

排序后进行处理,当然这样的方法对于离线的非常有效,在线的还必须得二分,当然二分很纠结。

/* * File: main.cpp * Author: hit-acm * * Created on 2012年8月14日, 下午1:14 */ #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <bitset> using namespace std; const int MAXM = 105; const int MAXN = 1010; const long long INF = 0x7fffffffffffffffLL; int m, n, x; long long t1[MAXN]; long long t2[MAXN]; struct Dragon { long long val; long long x; long long dp; bool operator<(const Dragon & a)const { return x < a.x; } } mat[MAXM][MAXN]; struct sort_index { int index; long long x; bool color; bool operator<(const sort_index & a)const { return x < a.x; } } temp[2 * MAXN]; long long solve() { for (int i = 0; i < m; i++) { sort(mat[i], mat[i] + n); } for (int i = 0; i < n; i++) { mat[0][i].dp = mat[0][i].val + abs(mat[0][i].x - x); } for (int i = 1; i < m; i++) { for (int k = 0; k < n; k++) { temp[k].x = mat[i - 1][k].x; temp[k].index = k; temp[k].color = true; temp[n + k].x = mat[i][k].x; temp[n + k].index = k; temp[n + k].color = false; } sort(temp, temp + 2 * n); long long min_dis = INF; for (int k = 0; k < 2 * n; k++) { if (temp[k].color == true) { min_dis = min(min_dis, mat[i - 1][temp[k].index].dp - temp[k].x); } else { t1[temp[k].index] = min_dis; } } min_dis = INF; for (int k = 2 * n - 1; k >= 0; k--) { if (temp[k].color == true) { min_dis = min(min_dis, mat[i - 1][temp[k].index].dp + temp[k].x); } else { t2[temp[k].index] = min_dis; } } for (int j = 0; j < n; j++) { mat[i][j].dp = INF; if (t1[j] != INF) { mat[i][j].dp = min(mat[i][j].dp, mat[i][j].x + t1[j]); } if (t2[j] != INF) { mat[i][j].dp = min(mat[i][j].dp, -mat[i][j].x + t2[j]); } mat[i][j].dp += mat[i][j].val; } } long long res = mat[m - 1][0].dp; for (int i = 1; i < n; i++) { res = min(res, mat[m - 1][i].dp); } return res; } int main() { int T; scanf("%d", &T); while (T--) { scanf("%d%d%d", &m, &n, &x); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { scanf("%lld", &mat[i][j].x); } } for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { scanf("%lld", &mat[i][j].val); } } printf("%lld\n", solve()); } return 0; }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值