2013 ACM/ICPC 亚洲区 杭州站

题目链接  2013杭州区域赛

Problem A

Problem B

这题我用的是SPFA+ mask dp

首先跑5次SPFA:

1次是求出每个起点和其他所有点的最短距离

4次是求出每个输入的点和其他所有点的最短距离

然后就是dp

设dp[mask][i]为,mask状态下,以i为终点的最优方案
然后做一遍状压DP即可。

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)

const int N = 103;
const int M = 1e4 + 10;
const int dx[] = {1, 0, -1, 0};
const int dy[] = {0, 1, 0, -1};

bool inqueue[M], fl;
int c[N][N], f[6][6], a[M], d[M], dp[101][6];
char s[N][N];
int cnt, n, m, k;
vector <int> v[M];

inline void addedge(int x, int y){
	v[x].push_back(y);
	v[y].push_back(x);
}

void SPFA(int s){
	memset(inqueue, false, sizeof inqueue);
	rep(i, 1, cnt) d[i] = 1 << 29;
	d[s] = 0;
	queue <int> q;
	q.push(s);

	while (!q.empty()){
		int x = q.front();
		q.pop();
		inqueue[x] = false;
		for (auto u : v[x]){
			if (d[u] > d[x] + 1){
				d[u] = d[x] + 1;
				if (!inqueue[u]){
					inqueue[u] = true;
					q.push(u);
				}
			}
		}
	}
}

int main(){

	while (~scanf("%d%d", &n, &m), n + m){
		rep(i, 1, n) scanf("%s", s[i] + 1);
		cnt = 0;
		rep(i, 1, n) rep(j, 1, m) c[i][j] = ++cnt;

		scanf("%d", &k);
		rep(i, 1, n) rep(j, 1, m) if (s[i][j] == '@'){
			a[k] = c[i][j];
			s[i][j] = '.';
			break;
		}

		rep(i, 0, k - 1){
			int x, y;
			scanf("%d%d", &x, &y);
			a[i] = c[x][y];
		}

		rep(i, 0, n * m + 1) v[i].clear();

		rep(i, 1, n){
			rep(j, 1, m) if (s[i][j] == '.'){
				rep(k, 0, 3){
					int x = i + dx[k], y = j + dy[k];
					if (s[x][y] == '.'){
						addedge(c[i][j], c[x][y]);
					}
				}
			}
		}

		SPFA(a[k]);

		rep(i, 0, k) rep(j, 0, k) f[i][j] = 1 << 29;
		rep(i, 0, k){
			SPFA(a[i]);
			rep(j, 0, k) if (i == j) f[i][j] = 0;
			else f[i][j] = d[a[j]];
		}

		rep(i, 0, 53)  rep(j, 0, 5) dp[i][j] = 1 << 29;
		rep(i, 0, k - 1) dp[1 << i][i] = f[i][k];
		
		rep(i, 1, ((1 << k) - 1)){
		       if (__builtin_popcount(i) != 1){
			       rep(j, 0, k - 1) if ((i >> j) & 1){
				       rep(l, 0, k - 1) if (((i >> l) & 1) && (j != l)){
					       dp[i][j] = min(dp[i][j], dp[i ^ (1 << j)][l] + f[j][l]);
				       }
			       }
		       }
		}

		int ans = 1 << 30;
		rep(i, 0, k - 1) ans = min(ans, dp[(1 << k) - 1][i]);
		printf("%d\n", ans < 1e6 ? ans : -1);
	}

	return 0;
}

 

 

Problem C

跟着题意模拟一遍

关键是那个旋转要一次性写对

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)

const int N = 41;


int a[N][N], b[N][N];
int n;
int ans;

void solve(){
	int c[N][N]; memset(c, 0, sizeof c);
	rep(i, 1, n) rep(j, 1, n) c[i][j] = a[j][n - i + 1];
	rep(i, 1, n) rep(j, 1, n) a[i][j] = c[i][j];
}


int main(){

	while (~scanf("%d", &n), n){
		rep(i, 1, n) rep(j, 1, n) scanf("%d", &a[i][j]);
		rep(i, 1, n) rep(j, 1, n) scanf("%d", &b[i][j]);

		ans = 0;
		rep(p, 1, 4){
			solve();
			int now = 0;
			rep(i, 1, n) rep(j, 1, n) if (a[i][j] == b[i][j]) ++now;
			ans = max(ans, now);
		}

		printf("%d\n", ans);
	}

	return 0;
}

 

Problem D

Problem E

Problem F

Problem G

Problem H

Problem I

Problem J

Problem K

 

posted @ 2017-10-03 22:31  cxhscst2  阅读(253)  评论(0编辑  收藏  举报