Homework Introduction

吃奶酪

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

struct node {
	double x, y;
} p[20];
double f[50000][16];

double dis(node a, node b) {
	return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> p[i].x >> p[i].y;
	}
	int N = (1 << n) - 1;
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= n; j++) {
			f[i][j] = 1e9;
		}
	}
	for (int i = 1; i <= n; i++) {
		f[1 << (i - 1)][i] = dis({0, 0}, p[i]);
	}
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= n; j++) {
			if ((i & (1 << (j - 1))) == 0)
				continue;
			for (int k = 1; k <= n; k++) {
				if (k == j)
					continue;
				if ((i & (1 << (k - 1))) == 0)
					continue;
				f[i][j] = min(f[i][j], f[i - (1 << (j - 1))][k] + dis(p[j], p[k]));
			}
		}
	}
	double res = 1e9;
	for (int i = 1; i <= n; i++) {
		res = min(res, f[N][i]);
	}
	cout << fixed << setprecision(2) << res << endl;
	return 0;
}

互不侵犯

/*
f[i][j][k]第i行摆成j的状态,用了k个棋子的方法总数

f[i][j][k]+=f[i-1][s][k-need[j]]

need[i]摆成i这样的状态,需要多少个棋子
10101011
*/
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n, m, f[10][1024][82], need[1025], can[1025];
signed main() {
	cin >> n >> m;
	int N = (1 << n) - 1;
	for (int i = 0; i <= N; i++) {
		int x = i;
		while (x) {
			if (x % 2 == 1)
				need[i]++;
			x /= 2;
		}
		if ((i & (i >> 1)) == 0 && (i & (i << 1)) == 0)
			can[i] = 1;
	}
	for (int i = 0; i <= N; i++) {
		if (can[i] == 1) {
			f[1][i][need[i]] = 1;
		}
	}
	for (int i = 2; i <= n; i++) {
		//枚举第i行的状态j
		for (int j = 0; j <= N; j++) {
			if (can[j] == 0)
				continue;
			//枚举上一行的状态s
			for (int s = 0; s <= N; s++) {
				if (can[s] == 0)
					continue;
				if ((s & j) != 0)
					continue;
				if ((j & (s << 1)) != 0)
					continue;
				if ((j & (s >> 1)) != 0)
					continue;
				//枚举用了棋子的总数
				for (int l = m; l >= need[j]; l--) {
					f[i][j][l] += f[i - 1][s][l - need[j]];
				}
			}
		}
	}
	int res = 0;
	for (int i = 0; i <= N; i++) {
		res += f[n][i][m];
	}
	cout << res << endl;
	return 0;
}

关灯问题II

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

struct node {
	int status, cost;
};
int n, m, a[105][11], book[1025];

int main() {
	cin >> n >> m;
	for (int i = 1; i <= m; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> a[i][j];
		}
	}
	queue<node>q;
	book[(1 << n) - 1] = 1;
	q.push({((1 << n) - 1), 0});
	while (!q.empty()) {
		node tmp = q.front();
		q.pop();
		if (tmp.status == 0) {
			cout << tmp.cost << endl;
			return 0;
		}
		for (int i = 1; i <= m; i++) {
			int status = tmp.status;
			for (int j = 1; j <= n; j++) {
				if (a[i][j] == 0)
					continue;
				else if (a[i][j] == 1) {
					if ((status & (1 << (j - 1))) != 0)
						status -= (1 << (j - 1));
				} else if (a[i][j] == -1) {
					if ((status & (1 << (j - 1))) == 0)
						status += (1 << (j - 1));
				}
			}
			if (book[status] == 0) {
				book[status] = 1;
				q.push({status, tmp.cost + 1});
			}
		}
	}
	cout << -1 << endl;
	return 0;
}

孤岛营救问题

#include <bits/stdc++.h>
using namespace std;
int n, m, p, k;
int can[11][11][11][11], s;

int key[11][11], nxt[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
int book[11][11][1025];

struct node {
	int x, y, key, cost;
};

//can[a][b][c][d] ab点到cd的墙的种类
int main() {
	cin >> n >> m >> p >> k;
	for (int i = 1; i <= k; i++) {
		int x1, y1, x2, y2, g;
		cin >> x1 >> y1 >> x2 >> y2 >> g;
		if (g == 0) {
			can[x1][y1][x2][y2] = -1;
			can[x2][y2][x1][y1] = -1;
		} else {
			can[x1][y1][x2][y2] = g;
			can[x2][y2][x1][y1] = g;
		}
	}
	cin >> s;
	for (int i = 1; i <= s; i++) {
		int x, y, z;
		cin >> x >> y >> z;
		key[x][y] |= (1 << (z - 1));
	}
	queue<node>q;
	q.push({1, 1, key[1][1], 0});
	book[1][1][key[1][1]] = 1;
	while (!q.empty()) {
		node tmp = q.front();
		q.pop();
		if (tmp.x == n && tmp.y == m) {
			cout << tmp.cost << endl;
			return 0;
		}
		for (int i = 0; i < 4; i++) {
			int nx = tmp.x + nxt[i][0];
			int ny = tmp.y + nxt[i][1];
			if (nx >= 1 && nx <= n && ny >= 1 && ny <= m) {
				if (can[tmp.x][tmp.y][nx][ny] == 0) {
					int Key = tmp.key | key[nx][ny];
					if (book[nx][ny][Key] == 0) {
						book[nx][ny][Key] = 1;
						q.push({nx, ny, Key, tmp.cost + 1});
					}
				} else {
					if (can[tmp.x][tmp.y][nx][ny] == -1)
						continue;
					if ((tmp.key & (1 << (can[tmp.x][tmp.y][nx][ny] - 1))) == 0)
						continue;
					int Key = tmp.key | key[nx][ny];
					if (book[nx][ny][Key] == 0) {
						book[nx][ny][Key] = 1;
						q.push({nx, ny, Key, tmp.cost + 1});
					}
				}

			}
		}
	}
	cout << -1 << endl;
	return 0;
}

WIE

#include <bits/stdc++.h>
using namespace std;
const int N = 205;
int n, m, p, k, dis[N][10005];
int key[N];

struct node {
	int id, dis, key;
	friend bool operator < (node a, node b) {
		return a.dis > b.dis;
	}
};

struct edge {
	int v, w, monster;
};
vector<edge>e[N];

void dijkstra() {
	memset(dis, 0x3f, sizeof(dis));
	dis[1][key[1]] = 0;
	priority_queue<node>q;
	q.push((node) {
		1, 0, key[1]
	});
	int res = 1e9;
	while (!q.empty()) {
		node tmp = q.top();
		if (tmp.id == n) {
			cout << tmp.dis << endl;
			exit(0);
		}
		q.pop();
		for (int i = 0; i < e[tmp.id].size(); i++) {
			int v = e[tmp.id][i].v;
			int w = e[tmp.id][i].w;
			int monster = e[tmp.id][i].monster;
			if ((tmp.key & monster) == monster) {
				if (dis[v][tmp.key | key[v]] > tmp.dis + w) {
					dis[v][tmp.key | key[v]] = tmp.dis + w;
					q.push((node) {
						v, dis[v][tmp.key | key[v]], tmp.key | key[v]
					});
				}
			}
		}
	}
	cout << -1 << endl;
}

int main() {
	cin >> n >> m >> p >> k;
	for (int i = 1; i <= k; i++) {
		int x, t;
		cin >> x >> t;
		for (int j = 1; j <= t; j++) {
			int c;
			cin >> c;
			key[x] |= (1 << (c - 1));
		}
	}
	for (int i = 1; i <= m; i++) {
		int x, y, z, t;
		cin >> x >> y >> z >> t;
		int monster = 0;
		for (int j = 1; j <= t; j++) {
			int c;
			cin >> c;
			monster |= (1 << (c - 1));
		}
		e[x].push_back((edge) {
			y, z, monster
		});
		e[y].push_back((edge) {
			x, z, monster
		});
	}
	dijkstra();
	return 0;
}

售货员的难题

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 21;
int n, a[N][N], f[1 << N][N];

signed main() {
	cin >> n;
	for (int  i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> a[i][j];
		}
	}
	memset(f, 0x3f, sizeof(f));
	f[1][1] = 0;
	for (int i = 1; i <= (1 << n) - 1; i++) {
		for (int j = 1; j <= n; j++) {
			if (i & (1 << (j - 1))) {
				for (int k = 1; k <= n; k++) {
					if (j != k) {
						if (i & (1 << (k - 1))) {
							f[i][j] = min(f[i][j], f[i - (1 << (j - 1))][k] + a[k][j]);
						}
					}
				}
			}
		}
	}
	int res = 1e9;
	for (int i = 1; i <= n; i++) {
		res = min(f[(1 << n) - 1][i] + a[i][1], res);
	}
	cout << res;
	return 0;
}

炮兵阵地

/*
f[i][j][k]
f[i][j][k] = max(f[i-1][k][s]+need(j))
*/
#include <bits/stdc++.h>
using namespace std;
int n, m, can[101][1025], need[1025], f[101][1025][1025];
int mat[101];

int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			char x;
			cin >> x;
			if (x == 'P')
				mat[i] |= (1 << (j - 1));
		}
	}
	int N = (1 << m) - 1;
	for (int i = 0; i <= N; i++) {
		int x = i;
		while (x) {
			if (x % 2 == 1)
				need[i]++;
			x /= 2;
		}
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 0; j <= N; j++) {
			if ((j & (j << 1)) != 0)
				continue;
			if ((j & (j >> 1)) != 0)
				continue;
			if ((j & (j << 2)) != 0)
				continue;
			if ((j & (j >> 2)) != 0)
				continue;
			/*
			10101110
			00001111
			*/
			if ((mat[i] & j) != j)
				continue;
			can[i][j] = 1;
		}
	}
	for (int i = 0; i <= N; i++) {
		if (can[1][i] == 0)
			continue;
		for (int j = 0; j <= N; j++) {
			if (can[2][j] == 0)
				continue;
			if ((i & j) != 0)
				continue;
			f[2][j][i] = need[i] + need[j];
		}
	}
	for (int i = 3; i <= n; i++) {
		for (int j = 0; j <= N; j++) {
			if (can[i][j] == 0)
				continue;
			for (int k = 0; k <= N; k++) {
				if (can[i - 1][k] == 0)
					continue;
				if ((j & k) != 0)
					continue;
				for (int s = 0; s <= N; s++) {
					if (can[i - 2][s] == 0)
						continue;
					if ((s & k) != 0)
						continue;
					if ((s & j) != 0)
						continue;
					f[i][j][k] = max(f[i][j][k], f[i - 1][k][s] + need[j]);
				}
			}
		}
	}
	int res = 0;
	for (int i = 0; i <= N; i++) {
		for (int j = 0; j <= N; j++) {
			res = max(res, f[n][i][j]);
		}
	}
	if(n!=1){
		cout << res << endl;
	}
	else{
		res = 0;
		for(int i=0;i<=N;i++){
			if(can[1][i]){
				res = max(res,need[i]);
			}
		}
		cout<<res<<endl;
	}
	return 0;
}

Corn Fields G

/*
f[i][j]第i行摆成j样子的方法总数
f[i][j]+=f[i-1][k]
*/
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int Mod = 1e8;
int n, m, can[15][5000];
int f[15][5000];
int mat[15];

signed main() {
	cin >> n >> m;
	int N = (1 << m) - 1;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			int x;
			cin >> x;
			if (x == 1) {
				mat[i] |= (1 << (j - 1));
			}

		}
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 0; j <= N; j++) {
			if ((j & (j << 1)) != 0 || (j & (j >> 1)) != 0)
				continue;
			if ((mat[i] & j) != j)
				continue;
			can[i][j] = 1;
		}
	}
	for (int i = 0; i <= N; i++) {
		if (can[1][i] == 1)
			f[1][i] = 1;
	}
	for (int i = 2; i <= n; i++) {
		for (int j = 0; j <= N; j++) {
			if (can[i][j] == 0)
				continue;
			for (int k = 0; k <= N; k++) {
				if ((j & k) != 0)
					continue;
				if (can[i - 1][k] == 0)
					continue;
				f[i][j] += f[i - 1][k];
				f[i][j]%=Mod;
			}
		}
	}
	int res = 0;
	for (int i = 0; i <= N; i++) {
		res += f[n][i];res%=Mod;
	}
	cout << res%Mod << endl;
	return 0;
}
Status
Done
Problem
12
Open Since
2025-7-9 0:00
Deadline
2025-8-7 23:59
Extension
24 hour(s)