您的位置:首页 > 其它

2016-2017 ACM-ICPC Pacific Northwest Regional Contest (Div. 2) 题解

2018-02-03 16:38 856 查看
题目链接

A - Alphabet

最长公共子序列。保留最长公共子序列,剩余的删除或者补足即可。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 10;
char s[maxn];
char t[maxn];
int dp[100][100];

int main() {
scanf("%s", s);
for(int i = 0; i < 26; i ++) {
t[i] = i + 'a';
t[i + 1] = 0;
}
int lens = strlen(s);
int lent = strlen(t);
for(int i = 1; i <= lens; i ++) {
for(int j = 1; j <= lent; j ++) {
if(s[i - 1] == t[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;
else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
printf("%d\n", 26 - dp[lens][lent]);
return 0;
}


B - Barbells

暴力。枚举哪几个一定用,去剩余的那些里面枚举是否可以凑出和这几个一样的。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 10;
int n, m;
long long a[maxn], b[maxn];
long long ans[maxn];
long long p[maxn];
long long sum[maxn];
int sz, cnt;
long long B[maxn];
long long sumB[maxn];

int lowbit(int x) {
return x & (-x);
}

int main() {
cin >> n >> m;
for(int i = 0; i < n; i ++) cin >> a[i];
for(int i = 0; i < m; i ++) cin >> b[i];
for(int i = 1; i < (1 << m); i ++) {
for(int j = 0; j < m; j ++) {
if((1 << j) & i) sum[i] += b[j];
}
}
for(int i = 0; i < (1 << m); i ++) {
sz = 0;
for(int j = 0; j < m; j ++) {
if((1 << j) & i) continue;
B[sz ++] = b[j];
}
// sum[i];
if(sum[i] == 0) {
p[cnt ++] = sum[i];
continue;
}
sumB[0] = 0;
for(int j = 0; j < sz; j ++) {
sumB[1 << j] = B[j];
}
for(int j = 1; j < (1 << sz); j ++) {
sumB[j] = sumB[j - lowbit(j)] + sumB[lowbit(j)];
if(sumB[j] == sum[i]) {
p[cnt ++] = sum[i];
break;
}
}
}
sz = 0;
for(int i = 0; i < cnt; i ++) {
for(int t = 0; t < n; t ++) {
ans[sz ++] = p[i] * 2 + a[t];
}
}
sort(ans, ans + sz);
for(int i = 0; i < sz; i ++) {
if(i >= 1 && ans[i] == ans[i - 1]) continue;
printf("%lld\n", ans[i]);
}

return 0;
}

/*
2 5
100 110
5 5 1 4 6

*/


C - Buggy Robot

记$f[i][x][y]$表示操作了前$i$个指令,当前在$(x,y)$位置的最小费用。分析可以发现是一个边权只有$0$和$1$的最短路问题。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 60;
int dir[4][2] = {
{-1, 0},
{0, 1},
{1, 0},
{0, -1},
};

int n, m;
char s[maxn][maxn];
char op[maxn];
int len;
int dp[maxn][maxn][maxn];
int f[maxn][maxn][maxn];
int sx, sy, ex, ey;

int out(int x, int y) {
if(x < 0 || x >= n) return 1;
if(y < 0 || y >= m) return 1;
return 0;
}

int Hash(int a, int x, int y) {
return a * 10000 + x * 100 + y;
}

void Get(int st, int &a, int &x, int &y) {
y = st % 100;
st = st / 100;
x = st % 100;
st = st / 100;
a = st;
}

void work() {
queue<int> q;
dp[0][sx][sy] = 0;
f[0][sx][sy] = 1;
q.push(Hash(0, sx, sy));
while(!q.empty()) {
int st = q.front();
q.pop();
int a, x, y;
Get(st, a, x, y);
f[a][x][y] = 0;

/* insert */
for(int i = 0; i < 4; i ++) {
int tx = x + dir[i][0];
int ty = y + dir[i][1];
if(out(tx, ty)) continue;
if(s[tx][ty] == '#') continue;
if(dp[a][tx][ty] > dp[a][x][y] + 1) {
dp[a][tx][ty] = dp[a][x][y] + 1;
if(f[a][tx][ty] == 0) {
f[a][tx][ty] = 1;
q.push(Hash(a, tx, ty));
}
}
}

/* del */
if(a < len) {
if(dp[a + 1][x][y] > dp[a][x][y] + 1) {
dp[a + 1][x][y] = dp[a][x][y] + 1;
if(f[a + 1][x][y] == 0) {
f[a + 1][x][y] = 1;
q.push(Hash(a + 1, x, y));
}
}
}

/* use */
if(a < len) {
int d;
if(op[a] == 'U') d = 0;
if(op[a] == 'R') d = 1;
if(op[a] == 'D') d = 2;
if(op[a] == 'L') d = 3;

int tx = x + dir[d][0];
int ty = y + dir[d][1];
if(out(tx, ty) || s[tx][ty] == '#') {
tx = x;
ty = y;
}
if(dp[a + 1][tx][ty] > dp[a][x][y]) {
dp[a + 1][tx][ty] = dp[a][x][y];
if(f[a + 1][tx][ty] == 0) {
f[a + 1][tx][ty] = 1;
q.push(Hash(a + 1, tx, ty));
}
}
}
}
}

int main() {
scanf("%d%d", &n, &m);
for(int i = 0; i < n; i ++) {
scanf("%s", s[i]);
}
scanf("%s", op);
len = strlen(op);
for(int i = 0; i < n; i ++) {
for(int j = 0; j < m; j ++) {
if(s[i][j] == 'R') sx = i, sy = j;
if(s[i][j] == 'E') ex = i, ey = j;
for(int k = 0; k <= len; k ++) {
dp[k][i][j] = 100000;
}
}
}
work();
int ans = 100000;
for(int i = 0; i <= len; i ++) {
ans = min(ans, dp[i][ex][ey]);
}
printf("%d\n", ans);
return 0;
}

/*
3 3
R..
.#.
..E
LRDD

2 4
R.#.
#..E
RRUUDDRRUUUU
*/


D - Cameras

贪心。每一个区间看,贪心靠后放$1$即可。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 10;
int f[maxn];
int n, k, r;

int main() {
scanf("%d%d%d", &n, &k, &r);
for(int i = 1; i <= k; i ++) {
int x;
scanf("%d", &x);
f[x] = 1;
}
int ans = 0;
int sum = 0;
for(int i = 1; i <= r; i ++) {
sum += f[i];
}
int R = r;
while(sum < 2) {
if(f[R]) R --;
else {
sum ++;
f[R] = 1;
ans ++;
R --;
}
}
for(int i = r + 1; i <= n; i ++) {
sum -= f[i - r];
sum += f[i];
int L = i - r + 1;
int R = i;
while(sum < 2) {
if(f[R]) R --;
else {
sum ++;
f[R] = 1;
ans ++;
R --;
}
}
}
printf("%d\n", ans);
return 0;
}


E - Contest Score

优先队列。

#include <bits/stdc++.h>
using namespace std;

int n, k;
long long a[500];
priority_queue<long long> p;

int main() {
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; i ++) {
cin >> a[i];
}
long long ans = 0;
long long time = 0;
for(int i = 1; i <= k; i ++) {
p.push(-a[i]);
}
for(int i = k + 1; i <= n; i ++) {
long long u = -p.top();
p.pop();
time += u;
ans += time;
p.push(-a[i]);
}
while(!p.empty()) {
long long u = -p.top();
p.pop();
time += u;
ans += time;
}
cout << ans << endl;
return 0;
}


F - Equality

水题。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 10;
char s[maxn];

int main() {
int a, b, c;
cin >> a;
cin >> s;
cin >> b;
cin >> s;
cin >> c;
if(a + b == c) puts("YES");
else puts("NO");
return 0;
}


G - Gravity

模拟。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1000;
char s[maxn][maxn];

int main() {
int n, m;
scanf("%d%d", &n, &m);
for(int i = 0; i < n; i ++) {
scanf("%s", s[i]);
}
for(int i = n - 2; i >= 0; i --) {
for(int j = 0; j < m; j ++) {
if(s[i][j] != 'o') continue;
int x = i;
for(int k = i + 1; k < n; k ++) {
if(s[k][j] == '.') x = k;
else break;
}
s[i][j] = '.';
s[x][j] = 'o';
}
}
for(int i = 0; i < n; i ++) {
printf("%s\n", s[i]);
}
return 0;
}

/*
3 3
ooo
#..
..#

4 2
oo
oo
o.
..
*/


H - Islands

从每一个未被遍历过的$L$开始遍历,$C$当做$L$。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1010;
char s[maxn][maxn];
int n, m;
int ans;

int f[maxn][maxn];
int dir[4][2] = {
{0, -1},
{0, 1},
{1, 0},
{-1, 0},
};

int out(int x, int y) {
if(x < 0 || x >= n) return 1;
if(y < 0 || y >= m) return 1;
return 0;
}

void dfs(int x, int y) {
f[x][y] = 1;
for(int i = 0; i < 4; i ++) {
int tx = x + dir[i][0];
int ty = y + dir[i][1];
if(out(tx, ty)) continue;
if(s[tx][ty] == 'W') continue;
if(f[tx][ty]) continue;
dfs(tx, ty);
}
}

int main() {
scanf("%d%d", &n, &m);
for(int i = 0; i < n; i ++) {
scanf("%s", s[i]);
}
for(int i = 0; i < n; i ++) {
for(int j = 0; j < m; j ++) {
if(f[i][j]) continue;
if(s[i][j] == 'L') {
dfs(i, j);
ans ++;
}
}
}
cout << ans << endl;
return 0;
}

/*
4 5 CCCCC CCCCC CCCCC CCCCC
3 2 LW CC WL
*/


I - Mismatched Socks

二分。和这里的F题一样的做法,不再赘述。

#include <bits/stdc++.h>
using namespace std;

int T, n, k;
const int maxn = 1e5 + 10;
long long a[maxn];

int check(long long x) {
long long p = 0;
for(int i = 1; i <= n; i ++) {
p = p + min(x, a[i]);
}
if(p >= x * k) return 1;
return 0;
}

int main() {

scanf("%d", &n);
k = 2;
for(int i = 1; i <= n; i ++) {
scanf("%lld", &a[i]);
}
long long L = 0;
long long R = 1e12;
long long ans = 0;
while(L <= R) {
long long mid = (L + R) / 2;
if(check(mid)) ans = mid, L = mid + 1;
else R = mid - 1;
}
printf("%lld\n", ans);

return 0;
}


J - Postman

贪心。原点左侧和右侧分开计算。每一侧计算的时候由远及近进行操作即可。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 10;
struct X {
long long x;
long long m;
}s[maxn];
int n;
long long k;

bool cmp(const X& a, const X& b) {
return a.x < b.x;
}

int main() {
scanf("%d%lld", &n, &k);
for(int i = 1; i <= n; i ++) {
scanf("%lld%lld", &s[i].x, &s[i].m);
}
sort(s + 1, s + 1 + n, cmp);
long long ans = 0;
int p;
if(s[1].x <= 0) {
for(int i = 1; i <= n; i ++) {
if(s[i].x <= 0) p = i;
}
while(1) {
int now = -1;
for(int i = 1; i <= p; i ++) {
if(s[i].m) {
now = i;
break;
}
}
if(now == -1) break;
if(s[now].m >= k) {
long long ci = s[now].m / k;
ans = ans - ci * s[now].x;
s[now].m = s[now].m % k;
} else {
long long tmp = k;
ans = ans - s[now].x;
while(tmp) {
if(now > p) break;
long long A = min(tmp, s[now].m);
tmp = tmp - A;
s[now].m -= A;
now ++;
}
}
}
}
p = -1;
for(int i = 1; i <= n; i ++) {
if(s[i].x > 0) {
p = i;
break;
}
}
if(p != -1) {
while(1) {
int now = -1;
for(int i = p; i <= n; i ++) {
if(s[i].m) {
now = i;
}
}
if(now == -1) break;
if(s[now].m >= k) {
long long ci = s[now].m / k;
ans = ans + ci * s[now].x;
s[now].m = s[now].m % k;
} else {
long long tmp = k;
ans = ans + s[now].x;
while(tmp) {
if(now < p) break;
long long A = min(tmp, s[now].m);
tmp = tmp - A;
s[now].m -= A;
now --;
}
}
}
}
cout << ans * 2LL << endl;
return 0;
}

/*
4 10
-7 5
-2 3
5 7
9 5

7 1
9400000 10000000
9500000 10000000
9600000 10000000
9700000 10000000
9800000 10000000
9900000 10000000
10000000 10000000
*/


K - Six Sides

模拟。操作的次数越多,答案精度越高。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1000;
int a[maxn], b[maxn];

int main() {
double ping = 0;
double win = 0;
for(int i = 1; i <= 6; i ++) cin >> a[i];
for(int i = 1; i <= 6; i ++) cin >> b[i];
for(int i = 1; i <= 6; i ++) {
for(int j = 1; j <= 6; j ++) {
if(a[i] == b[j]) ping ++;
if(a[i] > b[j]) win ++;
}
}
ping /= 36.0;
win /= 36.0;
double ans = 0.0;
double x = 1.0;
for(int i = 1; i <= 1000000; i ++) {
ans = ans + x * win;
x = x * ping;
}
printf("%.5f\n", ans);
return 0;
}


L - Three Square

暴力枚举所有情况。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 5e5 + 10;
int n, m;
int a[maxn], b[maxn];
int t[maxn];

int A[maxn], B[maxn];

int main() {

cin >> a[0] >> b[0];
cin >> a[1] >> b[1];
cin >> a[2] >> b[2];

t[0] = 0, t[1] = 1, t[2] = 2;

int ok = 0;

do {
// printf("%d %d %d\n", t[0], t[1], t[2]);
for(int i = 0; i < 8; i ++) {
for(int j = 0; j < 3; j ++) {
if((i << j) & i) {
B[j] = a[t[j]];
A[j] = b[t[j]];
} else {
A[j] = a[t[j]];
B[j] = b[t[j]];
}
}

// 1
if(A[0] == A[1] && A[0] == A[2]
&& B[0] + B[1] + B[2] == A[0]) ok = 1;

// 2
if(B[0] == B[1] && B[0] == B[2]
&& A[0] + A[1] + A[2] == B[0]) ok = 1;

// 3
if(B[1] + B[2] == B[0] && A[1] == A[2]
&& A[1] + A[0] == B[0]) ok = 1;

// 5
if(B[1] == B[2] && A[1] + A[2] == A[0]
&& A[0] == B[0] + B[1]) ok = 1;

}
} while(next_permutation(t, t + 3));

if(ok) puts("YES");
else puts("NO");

return 0;
}


M - Zigzag

记录以每个位置为结尾的且在波峰以及波谷的最长序列长度,和LIS一样转移即可。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 2000000;

int n;
int d[maxn];
int dp[maxn][2];

int main() {
cin >> n;
for(int i = 1; i <= n; i ++) {
cin >> d[i];
}
int ans = 0;
for(int i = 1; i <= n; i ++) {
int mx = 0;
// dp[i][0];
for(int j = 1; j < i; j ++) {
if(d[j] > d[i]) mx = max(mx, dp[j][1]);
}
dp[i][0] = mx + 1;
ans = max(ans, dp[i][0]);

mx = 0;
// dp[i][1];
for(int j = 1; j < i; j ++) {
if(d[j] < d[i]) mx = max(mx, dp[j][0]);
}
dp[i][1] = mx + 1;
ans = max(ans, dp[i][1]);
}
cout << ans << endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐