首页 > 代码库 > indeed 5.13 第二次网测

indeed 5.13 第二次网测

题目描述,我找不见了,大概写一下想法和代码吧。

1. 没有看

2. 由于数据范围很小,就是简单的枚举,求全排列,然后更新答案。

技术分享
 1 #include<bits/stdc++.h> 2 #define pb push_back 3 typedef long long ll; 4 using namespace std; 5 typedef pair<int, int> pii; 6 const int maxn = 1e3 + 10; 7 int n, k, m; 8 int a[50], b[50], u[50]; 9 bool ina[10], inb[10];10 int work() {11     int r = 0;12     for (int i = 0; i < m; i++) {13         if(ina[a[i] ] && ina[b[i] ])14             r += u[i];15         if(inb[a[i] ] && inb[b[i] ])16             r += u[i];17     }18     return r;19 }20 void solve() {21     cin >> n >> k >> m;22     for (int i = 0; i < m; i++) {23         cin >> a[i] >> b[i] >> u[i];24     }25     vector<int> p;26     for (int i = 1; i <= n; i++)27         p.push_back(i);28     int res = 0;29     do {30         memset(ina, 0, sizeof ina);31         memset(inb, 0, sizeof inb);32         for (int i = 0; i < k; i++)33             ina[p[i] ] = 1;34         for (int i = k; i < k * 2; i++)35             inb[p[i] ] = 1;36         res = max(res, work());37     } while(next_permutation(p.begin(), p.end()));38     cout << res << endl;39 }40 41 int main() {42     freopen("test.in", "r", stdin);43     //freopen("test.out", "w", stdout);44     ios::sync_with_stdio(0);45     cin.tie(0); cout.tie(0);46     solve();47     return 0;48 }
View Code

3. 这次第三题挺有意思的,求左上角到右下角的最短路径,但是多了一种跳的操作。

我的想法很简单,由于在每一个点上都可以选择跳与不跳,而且只能一次跳, 那就预处理出每个点到起始点的距离,每个点到终点的距离,然后遍历每一个点,更新答案。

一个是这个点到起点的距离加上到终点的距离, 一个是这个点到起点的距离 + 1(完成跳的动作) + 跳之后的点到终点的距离。更新答案。

技术分享
 1 #include<bits/stdc++.h> 2 #define pb push_back 3 typedef long long ll; 4 using namespace std; 5 typedef pair<int, int> pii; 6 const int maxn = 1e3 + 10; 7 const int inf = 1e5; 8 int h, w, d, r; 9 string a[15];10 int sdis[15][15], edis[15][15];11 int dx[] = {0, 0, 1, -1};12 int dy[] = {1, -1, 0, 0};13 bool check(int x, int y) {14     if(x < 0 || x >= h || y < 0 || y >= w) return 0;15     return 1;16 }17 void dfs(int x, int y, int v) {18     sdis[x][y] = v;19     for (int i = 0; i < 4; i++) {20         int cx = x + dx[i], cy = y + dy[i];21         if(check(cx, cy) && a[cx][cy] != # && sdis[cx][cy] > v + 1) {22             dfs(cx, cy, v + 1);23         }24     }25 }26 void dfs1(int x, int y, int v) {27     edis[x][y] = v;28     for (int i = 0; i < 4; i++) {29         int cx = x + dx[i], cy = y + dy[i];30         if(check(cx, cy) && a[cx][cy] != # && edis[cx][cy] > v + 1) {31             dfs1(cx, cy, v + 1);32         }33     }34 }35 void solve() {36     cin >> h >> w >> d >> r;37     for (int i = 0; i < h; i++)38         cin >> a[i];39     for (int i = 0; i < h; i++) {40         for (int j = 0; j < w; j++)41             sdis[i][j] = edis[i][j] = inf;42     }43     dfs(0, 0, 0);44     dfs1(h - 1, w - 1, 0);45     int res = inf;46     for (int i = 0; i < h; i++) {47         for (int j = 0; j < w; j++) {48             int t1 = sdis[i][j] + edis[i][j];49             res = min(res, t1);50             int x = i + d, y = j + r;51             if(check(x, y)) {52                 int t2 = sdis[i][j] + edis[x][y] + 1;53                 res = min(res, t2);54             }55 56         }57     }58     if(res == inf) res = -1;59     cout << res << endl;60 }61 62 int main() {63     freopen("test.in", "r", stdin);64     //freopen("test.out", "w", stdout);65     ios::sync_with_stdio(0);66     cin.tie(0); cout.tie(0);67     solve();68     return 0;69 }
View Code

4. 目标函数是差的绝对值乘以权值之和, 考虑权值都相等的时候,这时候的最佳点就是中间的那个点(奇数个点是中间点,偶数个点是中间2个点之间的点都行)。

下面考虑权值r不相等的时候,这个函数其实是凹的, 这个性质很重要,可以进行二分查找,目标点是该点比它左右2点的函数值都要小, 如果该点比左边大,比右边小,那查找区间往左移动,否则往右移动。

技术分享
 1 #include<bits/stdc++.h> 2 #define pb push_back 3 typedef long long ll; 4 using namespace std; 5 typedef pair<int, int> pii; 6 const int maxn = 1e5 + 10; 7 ll len; 8 int n; 9 ll a[maxn];10 int r[maxn];11 ll work(ll x) {12     ll res = 0;13     for (int i = 0; i < n; i++) {14         res += abs(a[i] - x) * r[i];15     }16     return res;17 }18 void solve() {19     scanf("%lld%d", &len, &n);20     for (int i = 0; i < n; i++) {21         scanf("%lld%d", &a[i], &r[i]);22     }23     ll left = 0, right = len;24     ll res = -1;25     while(left < right) {26         ll mid = (left + right) / 2;27         ll r = work(mid);28         ll r1 = work(mid - 1);29         ll r2 = work(mid + 1);30         if(r <= r1 && r <= r2) {31             left = right = mid;32             break;33         } else if(r1 <= r && r <= r2) {34             right = mid - 1;35         } else if(r1 >= r && r >= r2) {36             left = mid + 1;37         }38     }39     if(left < 0) left++;40     if(left > len) left--;41     printf("%lld\n", work(left));42 }43 44 int main() {45     freopen("test.in", "r", stdin);46     //freopen("test.out", "w", stdout);47     solve();48     return 0;49 }
View Code

 

indeed 5.13 第二次网测