HGOI 20200803

人均200+的水题大赛
自然AK

T1 SJR 的西洋棋

送分,因为答案<=6,果断暴搜,复杂度 \(C(25,6)\)

有人说会爆栈但事实并不会

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

#define rep(i, a, b) for (int i = a; i <= b; i++)
#define per(i, a, b) for (int i = a; i >= b; i--)
#define siz(a) (int)a.size()
#define pb push_back
#define mp make_pair
#define ll long long
#define fi first
#define se second

const int N = 100010 ;

const int dx[] = {-1, 0, 1, 0} ;
const int dy[] = {0, 1, 0, -1} ;

int a[10][10], vis[10][10] ;
bool flg ;

void find(int x, int y) {
	vis[x][y] = 1 ;
	rep(i, 0, 3) {
		int tx = x + dx[i], ty = y + dy[i] ;
		if (tx >= 1 && tx <= 5 && ty >= 1 && ty <= 5 && !vis[tx][ty] && a[tx][ty]) {
			find(tx, ty) ;
		}
	}
}

bool check() {
	int fi = -1, fj = -1 ;
	rep(i, 1, 5)
	rep(j, 1, 5)
	if (a[i][j]) {
		fi = i, fj = j ;
		break ;
	}
	if (fi == -1) return true ;
	memset(vis, 0, sizeof(vis)) ;
	find(fi, fj) ;
	rep(i, 1, 5)
	rep(j, 1, 5)
	if (a[i][j] && !vis[i][j]) return false ;
	return true ;
}

void dfs(int x, int y, int rst) {
	if (flg) return ;
	if (x == 6) {
		if (check()) flg = true ;
		return ;
	} 
	int nx = x, ny = y ;
	ny++ ; 
	if (ny == 6) nx++, ny = 1 ;
	if (a[x][y]) dfs(nx, ny, rst) ;
	else {
		if (rst) {
			a[x][y] = 1 ;
			dfs(nx, ny, rst - 1) ;
			a[x][y] = 0 ;
		}
		dfs(nx, ny, rst) ;
	}
} 

signed main() {
	freopen("chess.in", "r", stdin) ;
	freopen("chess.out", "w", stdout) ;
	rep(i, 1, 5) {
		string s ; cin >> s ;
		rep(j, 1, 5) a[i][j] = (s[j - 1] == '1') ;
	}
//	rep(i, 1, 5) {
//		rep(j, 1, 5) cout << a[i][j] << " " ;
//		cout << endl ;
//	}
	rep(ans, 0, 6) {
//		cout<<ans<<endl;
		flg = false ;
		dfs(1, 1, ans) ;
		if (flg) {
			printf("%d\n", ans) ;
			return 0 ;
		}
	}

	return 0 ;
}

T2 SJR 的金字塔

这也是个很入门的最短路题

因为 \(nm\) 都很小,所以其实 \(floyd\) 比堆优化的 \(dijkstra\) 跑的还快!

对于每天边,我们假定它是最长的,然后判断最短路+其能否更新答案

时间复杂度 \(O(nlognm)\)

这个题目完全可以再放大数据范围的

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

#define rep(i, a, b) for (int i = a; i <= b; i++)
#define per(i, a, b) for (int i = a; i >= b; i--)
#define siz(a) (int)a.size()
#define pb push_back
#define mp make_pair
#define ll long long
#define fi first
#define se second

const int N = 100010 ;
const int iinf = 0x3f3f3f3f ;

int n, m, ans ;
vector <pair<int, int> > e[N] ;
int w[N], dis[N], vis[N] ;

struct node {
	int x, dis ;
	bool operator < (const node &a) const {
		return dis > a.dis ;
	} 
} ;

priority_queue <node> q ;

int dijkstra(int lim) {
	memset(dis, 0x3f, sizeof(dis)) ;
	memset(vis, 0, sizeof(vis)) ;
	dis[1] = 0 ; q.push((node) {1, dis[1]}) ;
	while (!q.empty()) {
		int x = q.top().x ; q.pop() ;
		if (vis[x]) continue ;
		vis[x] = 1 ;
		rep(i, 0, siz(e[x]) - 1) {
			int v = e[x][i].fi ;
			if (vis[v] || e[x][i].se > lim) continue ;
			if (dis[v] > dis[x] + e[x][i].se) {
				dis[v] = dis[x] + e[x][i].se ;
				q.push((node) {v, dis[v]}) ;
			}
		}
 	}
 	return dis[n] ;
}

signed main() {
	freopen("pyramid.in", "r", stdin) ;
	freopen("pyramid.out", "w", stdout) ;
	scanf("%d%d", &n, &m) ;
	rep(i, 1, m) {
		int u, v ; scanf("%d%d%d", &u, &v, &w[i]) ;
		e[u].pb(mp(v, w[i])) ;
		e[v].pb(mp(u, w[i])) ;
	}
	ans = iinf ;
	rep(i, 1, m) ans = min(ans, dijkstra(w[i]) + w[i]) ;
	printf("%d\n", ans) ;
	return 0 ;
}

T3 SJR 的神秘函数

这是一道明显的dp

\(dp[i]\) 表示模数为 \(i\) 最少需要操作几次可以达到

\(dp[i]+1->dp[(i*10+j)%n]\)

使用bfs实现,注意不能使用dfs,因为优先的是步数

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

#define rep(i, a, b) for (int i = a; i <= b; i++)
#define per(i, a, b) for (int i = a; i >= b; i--)
#define siz(a) (int)a.size()
#define pb push_back
#define mp make_pair
#define ll long long
#define fi first
#define se second

const int N = 1000010 ;

int k, n ;
int dp[N] ;
pair<int, int> pre[N] ;
queue <int> q ;

void find_ans() {
	vector <int> ans ;
	ans.pb(pre[0].se) ;
	int cur = pre[0].fi ;
	while (cur != 0) {
		ans.pb(pre[cur].se) ;
		cur = pre[cur].fi ; 
	}
	reverse(ans.begin(), ans.end()) ;
	rep(i, 0, siz(ans) - 1) printf("%d", ans[i]) ; cout << endl ; 
}

signed main() {
	freopen("sramoc.in", "r", stdin) ;
	freopen("sramoc.out", "w", stdout) ;
	scanf("%d%d", &k, &n) ;
	if (k == 10) {
		printf("%d\n", n) ;
		return 0 ;
	}
	if (n <= 1) {
		printf("%d\n", n) ;
		return 0 ;
	}
	memset(dp, -1, sizeof(dp)) ;
	dp[0] = 0 ; q.push(0) ;
	while (!q.empty()) {
		int x = q.front() ; q.pop() ;
		if (x == 0 && dp[x] != 0) break ;
		rep(j, (x == 0 ? 1 : 0), k - 1) {
			int nx = (x * 10 + j) % n ;
			if (dp[nx] != -1 && dp[nx] != 0) continue ;
			dp[nx] = dp[x] + 1 ;
			pre[nx] = mp(x, j) ;
			q.push(nx) ;
		}
	}
//	rep(i, 0, 6) cout << dp[i] << " " ; cout << endl ; 
	find_ans() ;

	return 0 ;
}

posted @ 2020-08-03 13:11  harryhqg  阅读(164)  评论(0编辑  收藏  举报