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 ;
}
加油ヾ(◍°∇°◍)ノ゙