4629 Knowledge for the masses 高效

题目大意:有一个人要找管理员,,但前进的路上有很多的障碍 移动一个障碍到相应行的空位置需要花费1点体力,距离不限 问花费的最少体力值是多少,能前进的路是哪几条

解题思路:参考了学长的代码 求出每条前进道路的需要花费的最小体力值,再进行比较就可以 难点刚好就是这个了 vis[i]代表将该行的i列位置扫清需要消耗的体力值,flag[i]表示可以将第i列的几个位置扫清,如果i == R,就表示该列可以前行了,zero[i]表示该行第i个0所在的位置,cost[i]表示清每行第i列障碍的体力和

;cost[maxn], flag[maxn], zero[maxn], num[maxn], vis[maxn], ans[maxn];int L, R;void input() {int n;scanf(“%d”, &n);int pos = 0, cnt = 0;memset(vis, -1, sizeof(vis));for(int i = 0; i < n; i++) {scanf(“%d”, &num[i]);if(num[i] == 0) {flag[pos++]++;zero[cnt++] = i;}else {int t = min(cnt, num[i]);pos += num[i];for(int j = 1; j <= t; j++) {int u = pos – j;vis[u] = i – zero[cnt – j] – j + 1;cost[u] += vis[u];flag[u]++;}}}reverse(num, num + n);cnt = 0;for(int i = 0; i < n; i++) {if(num[i] == 0) {zero[cnt++] = i;pos–;}else {int t = min(cnt, num[i]);pos -= num[i];for(int j = 0; j < t; j++) {int u = pos + j;if(vis[u] == -1) {vis[u] = i – zero[cnt – j – 1] – j;cost[u] += vis[u];flag[u]++;}else {int t = i – zero[cnt – j – 1] – j;cost[u] += min(0, t – vis[u]);}}}}}void solve() {int Min = INF, cnt = 0;for(int i = 0; i < L; i++) {if(flag[i] == R) {if(cost[i] < Min) {Min = cost[i];cnt = 0;}if(cost[i] == Min) {ans[cnt++] = i;}}}printf(“%d\n”, Min);for(int i = 0; i < cnt; i++)printf(“%d “, ans[i]);printf(“\n”);}void init() {memset(flag, 0, sizeof(flag));memset(cost, 0, sizeof(cost));for(int i = 0; i < R; i++)input();}int main() {int test;scanf(“%d”, &test);while(test–) {scanf(“%d%d”, &R, &L);init();solve();}return 0;}

偶尔,我一个人站在黄昏的荒野,

4629 Knowledge for the masses 高效

相关文章:

你感兴趣的文章:

标签云: