HGOI 20190714

最后一题各种坑爹玩野,被坑到80
还好没有像某奕一样被坑到40嘿嘿
整体海星,加油

T1 淘汰赛制(elimination)

很明显是概率 \(dp\)(其实可以模拟,而且很多人过了)

\(dp[i][j]\) 表示第 \(i\)\(j\) 还存活的概率
转移:$dp[i][j] = dp[i - 1][j] * \sum\limits_{k 是它可能遇到的} f[i - 1][k] * a[j][k] $

\(k\) 是一个区间, 但是必须满足经过 \(i\) 轮之后与 \(j\) 成为对手

这样的 \(k\) 满足一个一个性质,即 \(id(k)=id(j)±1, id(j) = (j-1)/2^{(i-1)}+1\)

\(±1\) 根据 \(id(j)\) 的奇偶而定

然后在 \(dp[n][i]\)\(max\) 即可

#include<bits/stdc++.h>
#define rep(i, a, b) for (int i = a; i <= b; i++) 
using namespace std;

const int N = 1 << 11 ;

int k, n, m, stp, ans ;
int a[N][N] ;
double f[N][N], Max ;
// f[i][j] 表到第 i 轮 j 获胜的概率
// f[i][j] = f[i - 1][j] * sum(f[i - 1][k] * a[j][k])

int id(int x) {
	return (x - 1) / stp + 1 ;
}

signed main() {
	freopen("elimination.in", "r", stdin) ;
	freopen("elimination.out", "w", stdout) ;
	scanf("%d", &n) ;
	rep(i, 1, (1 << n))
	rep(j, 1, (1 << n))
	scanf("%d", &a[i][j]) ;
	rep(j, 1, (1 << n)) f[0][j] = 1 ;
	stp = 1 ;
	rep(i, 1, n) {
		rep(j, 1, (1 << n)) {
		   	double s = 0 ;
	 	    f[i][j] = f[i - 1][j] ; 
	 	    int curid = id(j), beat ;
	 	    if (curid & 1) beat = curid + 1 ; 
			else beat = curid - 1 ;
			rep(k, 1, (1 << n)) if (id(k) == beat) s += f[i - 1][k] * a[j][k] / 100 ;
	        f[i][j] *= s ; 
        }
        stp *= 2 ;
    }
    rep(i, 1, (1 << n))
    if (f[n][i] > Max) {
     	Max = f[n][i] ; ans = i;
    }
    printf("%d\n", ans) ;
    return 0 ;
}

T2 种树(trees)

这题相对简单

首先对要求按 \(l\) 从小到大排序

然后考虑每个要求

对于一个操作,我们要将其完成,且其能够尽可能多的完成后面的要求

因此我们从后往前放树

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

#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 ;

int n, m, ans ;
int v[N] ;

struct node {
	int l, r, t ;
	bool operator < (const node &rhs) const {
		return r == rhs.r ? l < rhs.l : r < rhs.r ;
	}
} a[N] ;

signed main() {
	freopen("trees.in", "r", stdin) ;
	freopen("trees.out", "w", stdout) ;
	scanf("%d%d", &n, &m) ;
	rep(i, 1, m) scanf("%d%d%d", &a[i].l, &a[i].r, &a[i].t) ;
	sort(a + 1, a + m + 1) ;
//	rep(i, 1, m) printf("%d %d %d\n", a[i].l, a[i].r, a[i].t) ;
	rep(i, 1, m) 
	if (a[i].t > 0) {
		int pos = a[i].r ;
		ans += a[i].t ;
		rep(j, 1, a[i].t) {
			while (v[pos]) pos-- ;
			v[pos] = 1 ;
			rep(k, i + 1, m) if (a[k].l <= pos && pos <= a[k].r) a[k].t-- ;
		}
	}
	printf("%d\n", ans) ;
	return 0 ;
}

T3 软件开发(software)

一眼就二分

二分答案,我们只需要考虑能否实现

\(f[i][j]\) 表示前 \(i\) 个人做了 \(j\) 个任务 \(1\) 的模块后还能做的任务 \(2\) 的模块数

转移方程: \(f[i][j] = max(f[i][j], f[i - 1][k] + (x - (j - k) * d1[i]) / d2[i])\)

如果 \(f[n][m] >= m\) 答案就可以实现

注意两个坑点:

  1. 开始要全部赋 \(-∞\)
  2. 二分右边界不能太大,不然 \(dp\) 会爆 \(int\)

时间复杂度 \(O(N^3)\)

#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 iinf = 0x3f3f3f3f ;
const int N = 1010 ;

int f[N][N] ; // f[i][j] 表示前i个人做了j个任务1的模块后还能做的任务2的模块数 

int n, m, ans ;
int d1[N], d2[N] ;

bool check(int x) {
	memset(f, -1, sizeof(f)) ;
	f[0][0] = 0 ;
//	rep(i, 1, m) f[0][i] = -iinf ;
	rep(i, 1, n)
	rep(j, 0, m)
	rep(k, 0, j) 
	if (x >= (j - k) * d1[i] && f[i - 1][k] != -1)
	f[i][j] = max(f[i][j], f[i - 1][k] + (x - (j - k) * d1[i]) / d2[i]) ;
//	rep(i, 1, n) {
//		rep(j, 0, m) cout << f[i][j] << " " ;
//		cout << endl ;
//	}
	return f[n][m] >= m ;
} 

signed main() {
//	freopen("software.in", "r", stdin) ;
//	freopen("software.out", "w", stdout) ;
	scanf("%d%d", &n, &m) ;
	rep(i, 1, n) scanf("%d%d", &d1[i], &d2[i]) ;
	int l = 0, r = 20000, ans = 0 ;
	while (l <= r) {
		int mid = (l + r) >> 1 ;
		if (check(mid)) ans = mid, r = mid - 1 ;
		else l = mid + 1 ;
	}
//	ans = 0 ;
//	rep(i, max(0, l - 5), min(iinf, r + 5)) 
//	if (check(i)) {
//		ans = i ;
//		break ;
//	}
//	check(15) ;
	printf("%d\n", ans) ;

	return 0 ;
}


posted @ 2020-07-14 17:04  harryhqg  阅读(83)  评论(0编辑  收藏  举报