01分数规划

语文不好, 这个可能是一个题单

注: 按字典序排序, 而不是难度

想学可以去 oi-wiki , 讲的很好

CF11E Forward, march!

代码
#include <cstdio>
#include <cctype>
#include <iostream>
const int maxn = 2e6;
int n, s[maxn], c;
double dp[2][maxn];
inline double max(double a, double b){return a > b ? a : b;}
bool check(double mid){
    dp[1][0] = 0; dp[0][0] = -mid;
    for(int i = 1; i <= n; ++i){
        dp[1][i] = dp[0][i - 1] + (s[i] == 3) - mid;
        dp[0][i] = dp[1][i - 1] + (s[i] == 2) - mid;
        if(dp[1][i] < dp[0][i]) dp[1][i] = max(dp[1][i], dp[0][i] - mid);
        else                    dp[0][i] = max(dp[0][i], dp[1][i] - mid);
    }
    return dp[1][n] >= 0;
}

int main(){
    while(!isupper(c = getchar()));
    do{ 
        switch(c){
            case 'X' : c = 1; break;
            case 'L' : c = 2; break;
            case 'R' : c = 3; break;
        }
        if(c != 1 && s[n] == c) s[++n] = 1;
        s[++n] = c;
    }while(isupper(c = getchar()));
    if(s[n] == s[1]){
        if(s[n] == 2) s[++n] = 1; 
        else{ 
            for(int i = n; i; --i) s[i + 1] = s[i];
            s[1] = 1;
            ++n;
        }
    }
    double l = 0, r = 100, mid;
    while(r - l > 1e-12){
        mid = (l + r) / 2;
        if(check(mid / 100)) l = mid;
        else r = mid;
    }
    printf("%lf\n", (double)((int)(r * 1e6)) / 1e6);

    return 0;
}

Desert King

代码
#include <cmath>
#include <cstdio>
const int maxn = 1011;
int n;
double x[maxn], y[maxn], z[maxn];
double ash[maxn][maxn], lava[maxn][maxn], dis[maxn];
bool vis[maxn];
bool check(double l){
    double ret = 0;
    for(int i = 1; i <= n; ++i) dis[i] = 1e9, vis[i] = false;
    for(int i = 1; i <= n; ++i) for(int j = 1; j < i; ++j)
        ash[i][j] = ash[j][i] = fabs(z[j] - z[i]) - l * lava[i][j];
    dis[1] = 0;
    for(int i = 1; i <= n; ++i){ 
        int u = 0;
        for(int v = 1; v <= n; ++v) if(!vis[v] && dis[u] > dis[v]) u = v; vis[u] = true, ret += dis[u];
        for(int v = 1; v <= n; ++v) if(!vis[v] && dis[v] > ash[u][v]) dis[v] = ash[u][v];
    }
    return ret < 0;
}

int main(){
    dis[0] = 1e9;
    while(true){
        scanf("%d", &n);
        if(n == 0) return 0; 
        for(int i = 1; i <= n; ++i) scanf("%lf%lf%lf", x + i, y + i, z + i);
        for(int i = 1; i <= n; ++i) for(int j = 1; j < i; ++j)
            lava[i][j] = sqrt((long double)(x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]));
        double l = 0, r = 1e9, mid;
        while(r - l > 1e-5){
            mid = (l + r) / 2;
            if(check(mid)) r = mid;
            else l = mid;
        }
        printf("%.3lf\n", r);
    }

    return 0;
}

Dropping tests

代码
#include <cstdio>
#include <algorithm>
const int maxn = 1e5 + 5;
int a[maxn], b[maxn];
double c[maxn];
int n, k;
bool check(double mid){
    double ret = 0;
    for(int i = 1; i <= n; ++i) c[i] = mid * b[i] - a[i];
    std::sort(c + 1, c + n + 1);
    for(int i = 1; i <= k; ++i) ret -= c[i];
    return ret > 0;
}
int main(){
    while(true){
        scanf("%d%d", &n, &k); k = n - k;
        if(n == 0) return 0;
        for(int i = 1; i <= n; ++i) scanf("%d", a + i);
        for(int i = 1; i <= n; ++i) scanf("%d", b + i);
        double l = 0, r = 1e9, mid;
        while(r - l > 1e-6){
            mid = (l + r) / 2;
            if(check(mid)) l = mid;
            else r = mid;
        }
        printf("%.0f\n", r * 100);
    }
    return 0; 
}

P1570 KC喝咖啡 / LibreOJ - 149

代码(特别申明, 这个才是板子)
#include <cstdio>
#include <algorithm>
const int maxn = 1e5 + 5;
int a[maxn], b[maxn];
double c[maxn];
int n, k;
bool check(double mid){
    double ret = 0;
    for(int i = 1; i <= n; ++i) c[i] = mid * b[i] - a[i];
    std::sort(c + 1, c + n + 1);
    for(int i = 1; i <= k; ++i) ret -= c[i];
    return ret >= 0;
}
int main(){
    scanf("%d%d", &n, &k);
    for(int i = 1; i <= n; ++i) scanf("%d", a + i);
    for(int i = 1; i <= n; ++i) scanf("%d", b + i);
    double l = 0, r = 1e6, mid;
    while(r - l > 1e-6){
        mid = (l + r) / 2;
        if(check(mid)) l = mid;
        else r = mid;
    }
    printf("%.4lf\n", r);
    
    return 0;
}

P2868 [USACO07DEC]Sightseeing Cows G

代码
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
const int maxn = 2001;
inline int min(int a, int b){return a < b ? a : b;}
struct node{
    int v;double w;
    node(){}
    node(int a){v = a;}
};
int cnt[maxn], a[maxn];
double dis[maxn];
bool use[maxn];
std::vector<node> edge[maxn];
std::vector<int> b[maxn];
std::queue<int> que;
int n, m, u, v, w;
bool spfa(){
    for(int i = 1; i <= n; ++i) dis[i] = 1e12, cnt[i] = 0;
    while(!que.empty()){
        use[que.front()] = false;
        que.pop();
    }
    que.push(1);
    dis[1] = 0; use[1] = 1;
    while(!que.empty()){
        int u = que.front(); que.pop();
        use[u] = false;
        for(auto v : edge[u]){
            if(dis[v.v] > dis[u] + v.w){
                dis[v.v] = dis[u] + v.w;
                if(!use[v.v]){
                    if(++cnt[v.v] == n) return true;
                    use[v.v] = true;
                    que.push(v.v);
                }
            }
        }
    }
    return false;
}
bool check(double mid){
    for(int i = 1; i <= n; ++i)
        for(int j = 0; j < edge[i].size(); ++j)
            edge[i][j].w = mid * b[i][j] - a[i];
    return spfa();
}
int main(){
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i) scanf("%d", a + i);
    for(int i = 1; i <= m; ++i){
        scanf("%d%d%d", &u, &v, &w);
        edge[u].push_back((node)(v));
        b[u].push_back(w);
    }
    double l = 0, r = 1e3, mid;
    while(r - l > 1e-4){
        mid = (l + r) / 2;
        if(check(mid)) l = mid;
        else r = mid;
    }
    printf("%.2lf\n", r);

    return 0;
}

P3199 [HNOI2009]最小圈

代码(此题正解看不懂, 由于出题人受宇宙射线影响, 用栈优化才可以)
#include <cstdio>
#include <vector>
#include <queue>
const int maxn = 30000;
struct node{
    int to; double dis;
    node(){}
    node(int a, double b){to = a, dis = b;}
};
std::vector<node> lava[maxn];
std::queue<int> que;
int n, m, u, v; double w;
bool vis[maxn];
double dis[maxn];

bool dfs(int u, double l){
    vis[u] = true;
    for(auto v : lava[u]){
        if(dis[v.to] > dis[u] + v.dis - l){
            dis[v.to] = dis[u] + v.dis - l;
            if(vis[v.to] || dfs(v.to, l)) return true;
        }
    }
    return vis[u] = false;
}

bool check(double l){
    for(int i = 1; i <= n; ++i) dis[i] = 0, vis[i] = false;
    for(int i = 1; i <= n; ++i) if(dfs(i, l)) return true;
    return false;
}

int main(){
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= m; ++i){
        scanf("%d%d%lf", &u, &v, &w);
        lava[u].push_back(node(v, w));
    }
    double l = -1e7, r = 1e7, mid;
    while(r - l > 1e-10){
        mid = (l + r) / 2;
        if(check(mid)) r = mid;
        else l = mid;
    }
    printf("%.8lf\n", r);

    return 0;
}

P3778 [APIO2017] 商旅

代码(压行的享受)
#include <cstdio>
typedef long long ll;
const int maxn = 1110, inf = 1215948680;
ll dis[maxn][maxn], val[maxn][maxn];
int w[2][maxn][maxn];
int n, m, k, u, v, a;
ll ash[maxn][maxn];
int l = 0, r = 1e9, mid;
inline ll min(ll a, ll b){return a < b ? a : b;}
inline ll max(ll a, ll b){return a > b ? a : b;}
bool check(ll mid){
    for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) ash[i][j] = val[i][j] - dis[i][j] * mid;
    for(int l = 1; l <= n; ++l) for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) ash[i][j] = max(ash[i][j], ash[i][l] + ash[l][j]);
    for(int i = 1; i <= n; ++i) if(ash[i][i] >= 0) return true;
    return false;
}
int main(){
    scanf("%d%d%d", &n, &m, &k);
    for(int i = 1; i <= n; ++i) for(int j = 1; j <= k; ++j) scanf("%d%d", w[0][i] + j, w[1][i] + j);
    for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) dis[i][j] = inf;
    for(int i = 1; i <= m; ++i){ scanf("%d%d%d", &u, &v, &a); dis[u][v] = a; }
    for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) for(int l = 1; l <= k; ++l) if(w[0][i][l] != -1 && w[1][j][l] != -1) val[i][j] = max(val[i][j], w[1][j][l] - w[0][i][l]); 
    for(int l = 1; l <= n; ++l) for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) dis[i][j] = min(dis[i][j], dis[i][l] + dis[l][j]);
    while(l <= r){ mid = l + r >> 1; if(check(mid)) l = mid + 1; else r = mid - 1; }
    printf("%d\n", r);
    
    return 0;
}

P4322 [JSOI2016]最佳团体

代码
#include <cstdio>
const int maxn = 2505;
double dp[maxn][maxn];
int n, m;
int a[maxn], b[maxn], fa[maxn], siz[maxn];
inline double min(double a, double b){return a < b ? a : b;}
inline double max(double a, double b){return a > b ? a : b;}
inline int min(int a, int b){return a < b ? a : b;}
inline int max(int a, int b){return a > b ? a : b;}
bool check(double l){
	for(int i = 0; i <= n; ++i){
		for(int j = 1; j <= siz[i]; ++j) dp[i][j] = -1e9;
		siz[i] = 1;
		dp[i][1] = (double)a[i] - l * b[i];
	}
	for(int i = n; i; --i){
		for(int j = min(m, siz[fa[i]]); j; --j)
			for(int k = 0; k <= min(m - j, siz[i]); ++k)
				dp[fa[i]][j + k] = max(dp[fa[i]][j + k], dp[fa[i]][j] + dp[i][k]);
		siz[fa[i]] += siz[i];
	}
	return dp[0][m] > 0;
}
int main(){
	scanf("%d%d", &m, &n); ++m;
	for(int i = 1; i <= n; ++i) scanf("%d%d%d", b + i, a + i, fa + i);
	double l = 0, r = 1e9, mid;
	while(r - l > 1e-5){
		mid = (l + r) / 2;
		if(check(mid)) l = mid;
		else r = mid;
	}
	printf("%.3lf", r);
	
	return 0;
}
/*end like this

I made a promise I swore I′d keep,
我发誓 我会坚持到底,
All that I wanted was to find something to live for,
我只想寻得一股支撑我活下去的力量,
Something to stand for,
还有立足之物,
And if I die for what I believe then this was worth it,
若是为信仰献身 我会毫不畏惧,
And all the hurting is only memory,
一切伤痛终究成为过往,
I'm up against the edge, but I won't runaway,
我会在死亡的边缘奋力抗争 但我决不选择逃亡,
The sky is turning red, but I still got my faith,
天空渐渐染上血色 但我依旧满怀信心,
I feel it in my bones,
我感到那股力量就在我的骨子里,
Yeah, I think I've always known it would end like this,
我想这一切都将如我所愿般结束,
Ooh-ooh-ooh,
It would end like this,
一切都将如愿而终,
Ooh-ooh-ooh,
It would end like this,
一切都将如愿而终,
Ooh-ooh-ooh,
It would end like this,
一切都将如愿而终,
Ooh-ooh-ooh,
It would end like this,
一切都将如愿而终,
I won't say I'm sorry, you made your choice,
我不会道歉 你早已下定决心,
We're not that different are we?
我们并非与众不同 不是吗,
I hear your voice inside me,
灵魂深处传来了你的声音,
Yeah, you remind me to keep on fighting with all my heart,
你再三提醒我 全力以赴投身于战火,
Just like you told me,
就像你对我说过的那样,
Nothing can stop me from getting what I want,
什么都无法阻止我 去追寻那心之所欲,
I'm up against the edge, but I won't runaway,
我会在死亡的边缘奋力抗争 但我决不选择逃亡,
The sky is turning red, but I still got my faith,
天空渐渐染上血色 但我依旧满怀信心,
I feel it in my bones,
我感到那力量就存于内心深处,
Yeah, I think I've always known it would end like this,
我想这一切都将如我所愿般结束,
Ooh-ooh-ooh,
It would end like this,
一切都将如愿而终,
Ooh-ooh-ooh,
It would end like this,
一切都将如愿而终,
Ooh-ooh-ooh,
It would end like this,
一切都将如愿而终,
Ooh-ooh-ooh,
It would end like this,
一切都将如愿而终,
In my heart I knew it we'd end up here,
我心里明白 我们终究会抵达这里,
Walking through the ruins,
穿行在废墟之间,
But there's no tears on my face,
但我的脸上丝毫没有泪水,
I know it's too late to try and tempt fate,
我知道 我已经来不及去改变命运,
As if I could, I'll never hold back,
如果可以 我不会再隐瞒什么,
I know you know that you always understood,
毕竟这些 你我都心知肚明。
*/

P4377 [USACO18OPEN] Talent Show G

代码
#include <cstdio>
const int maxn = 1002;
int n, m, a[maxn], b[maxn];
double dp[maxn];
inline double max(double a, double b){return a > b ? a : b;}
bool check(double l){
    dp[0] = 0;
    for(int i = 1; i <= m; ++i) dp[i] = -1e18;
    for(int i = 1; i <= n; ++i){
        for(int j = m; ~j; --j){
            int to = j + b[i]; if(to > m) to = m;
            dp[to] = max(dp[to], dp[j] + a[i] - l * b[i]);
        }
    }
    return dp[m] >= 0;
}
int main(){
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; ++i) scanf("%d %d", b + i, a + i);
    double l = 0, r = 5e5, mid;
    while(r - l > 1e-5){
        mid = (l + r) / 2;
        if(check(mid)) l = mid;
        else r = mid;
    }
    int ans = l * 1000;
    printf("%d\n", ans);

    return 0;
}

P5319 [BJOI2019]奥术神杖

代码(差点粘成别人的)
// 前置知识: AC自动机上跑DP, 慎做
#include <cmath>
#include <cstdio>
#include <cstring>
const int maxn = 1510;
struct auto_AC{
    int son[maxn][10], fail[maxn], cnt;
    double val[maxn];int sum[maxn];
    void add(char* s, double _){
        int n = strlen(s), now = 0;
        for(int i = 0; i < n; ++i){
            if(!son[now][s[i] ^ 48]) son[now][s[i] ^ 48] = ++cnt;
            now = son[now][s[i] ^ 48];
        }
        val[now] = _;
        sum[now] = 1;
    }
    int que[maxn], hd, tl;
    void build(){
        for(int i = 0; i < 10; ++i) if(son[0][i]) que[++tl] = son[0][i];
        while(hd < tl){
            int now = que[++hd];
            for(int i = 0; i < 10; ++i){
                if(son[now][i]){
                    fail[son[now][i]] = son[fail[now]][i];
                    que[++tl] = son[now][i];
                }else son[now][i] = son[fail[now]][i];
            }
            val[now] += val[fail[now]];
            sum[now] += sum[fail[now]];
        }
    }
}trie;
int n, m, val;
char T[maxn], s[maxn];
double dp[maxn][maxn];
int ash[2][maxn][maxn];

bool check(double mid){
    for(int i = 0; i <= n; ++i) for(int j = 0; j <= trie.cnt; ++j) dp[i][j] = -1e9;
    dp[0][0] = 0;
    for(int i = 0; i < n; ++i){
        for(int j = 0; j <= trie.cnt; ++j){
            if(dp[i][j] == -1e9) continue;
            if(T[i] == '.'){
                for(int k = 0; k < 10; ++k){
                    int to = trie.son[j][k];
                    if(dp[i + 1][to] < dp[i][j] + trie.val[to] - mid * trie.sum[to]){
                        dp[i + 1][to] = dp[i][j] + trie.val[to] - mid * trie.sum[to];
                        ash[0][i + 1][to] = j;
                        ash[1][i + 1][to] = k;
                    }
                }
            }else{
                int to = trie.son[j][T[i] ^ 48];
                if(dp[i + 1][to] < dp[i][j] + trie.val[to] - mid * trie.sum[to]){
                    dp[i + 1][to] = dp[i][j] + trie.val[to] - mid * trie.sum[to];
                    ash[0][i + 1][to] = j;
                    ash[1][i + 1][to] = T[i] ^ 48;
                }
            }
        }
    }
    int ret = 0;
    for(int i = 1; i <= trie.cnt; ++i) if(dp[n][i] > dp[n][ret]) ret = i;
    for(int i = n, j = ret; i; j = ash[0][i][j], --i){
        s[i - 1] = ash[1][i][j] ^ 48;
    }
    return dp[n][ret] > 0;
}
int main(){
    scanf("%d%d%s", &n, &m, T);
    for(int i = 1; i <= m; ++i){
        scanf("%s%d", s, &val);
        trie.add(s, log((double)val));
    }
    trie.build();
    double l = 0, r = log(1e9), mid;
    while(r - l > 1e-8){
        mid = (l + r) / 2;
        if(check(mid)) l = mid;
        else r = mid;
    }
    check(l);
    printf("%s\n", s);

    return 0;
}

P6087 [JSOI2015]送礼物

代码
#include <cstdio>
const int maxn = 5e4 + 5;
int n, k, l, r;
int a[maxn], que[maxn], hd, tl;
double max(double a, double b){return a > b ? a : b;}
bool check(double mid){
    #define c(i) ((double)a[i] - mid * (i))
    hd = 1, tl = 0;
    for(int i = l; i <= n; ++i){
        while(hd <= tl && c(i - l + 1) <= c(que[tl])) --tl;
        que[++tl] = i - l + 1;
        if(i - que[hd] >= r) ++hd;
        if(c(i) - c(que[hd]) >= mid * k) return true;
    }
    #undef c
    #define c(i) ((double)a[i] + mid * (i))
    hd = 1, tl = 0;
    for(int i = l; i <= n; ++i){
        while(hd <= tl && c(i - l + 1) >= c(que[tl])) --tl;
        que[++tl] = i - l + 1;
        if(i - que[hd] >= r) ++hd;
        if(c(que[hd]) - c(i) >= mid * k) return true;
    }
    #undef c
    return false;
}
double La_Pluma(){
    double ret = 0;
    hd = 1, tl = 0;
    for(int i = 1; i <= n; ++i){
        while(hd <= tl && a[que[tl]] >= a[i]) --tl;
        que[++tl] = i;
        if(i - que[hd] >= l) ++hd;
        ret = max(ret, (double)(a[i] - a[que[hd]]) / (l + k - 1));
    }
    hd = 1, tl = 0;
    for(int i = 1; i <= n; ++i){
        while(hd <= tl && a[que[tl]] <= a[i]) --tl;
        que[++tl] = i;
        if(i - que[hd] >=  l) ++hd;
        ret = max(ret, (double)(a[que[hd]] - a[i]) / (l + k - 1));
    }
    return ret;
}
int main(){
	int T; scanf("%d", &T);
	while(T--){
		scanf("%d%d%d%d", &n, &k, &l, &r);
		for(int i = 1; i <= n; ++i) scanf("%d", a + i);
		double ansl = 0, ansr = 1000, mid;
		while(ansr - ansl > 1e-6){
			mid = (ansl + ansr) / 2;
			if(check(mid)) ansl = mid;
			else ansr = mid;
		}
		printf("%.4lf\n", max(ansl, La_Pluma()));
	}
	
	return 0;
}


这个题的作用是提醒不是所有题都可以二分的呢(主要是在学分数规划的几天里看啥都想二分)

别想了, 没有涩图, 但是有歌词

the end

end like this

I made a promise I swore I′d keep,
我发誓 我会坚持到底,
All that I wanted was to find something to live for,
我只想寻得一股支撑我活下去的力量,
Something to stand for,
还有立足之物,
And if I die for what I believe then this was worth it,
若是为信仰献身 我会毫不畏惧,
And all the hurting is only memory,
一切伤痛终究成为过往,
I'm up against the edge, but I won't runaway,
我会在死亡的边缘奋力抗争 但我决不选择逃亡,
The sky is turning red, but I still got my faith,
天空渐渐染上血色 但我依旧满怀信心,
I feel it in my bones,
我感到那股力量就在我的骨子里,
Yeah, I think I've always known it would end like this,
我想这一切都将如我所愿般结束,
Ooh-ooh-ooh,
It would end like this,
一切都将如愿而终,
Ooh-ooh-ooh,
It would end like this,
一切都将如愿而终,
Ooh-ooh-ooh,
It would end like this,
一切都将如愿而终,
Ooh-ooh-ooh,
It would end like this,
一切都将如愿而终,
I won't say I'm sorry, you made your choice,
我不会道歉 你早已下定决心,
We're not that different are we?
我们并非与众不同 不是吗,
I hear your voice inside me,
灵魂深处传来了你的声音,
Yeah, you remind me to keep on fighting with all my heart,
你再三提醒我 全力以赴投身于战火,
Just like you told me,
就像你对我说过的那样,
Nothing can stop me from getting what I want,
什么都无法阻止我 去追寻那心之所欲,
I'm up against the edge, but I won't runaway,
我会在死亡的边缘奋力抗争 但我决不选择逃亡,
The sky is turning red, but I still got my faith,
天空渐渐染上血色 但我依旧满怀信心,
I feel it in my bones,
我感到那力量就存于内心深处,
Yeah, I think I've always known it would end like this,
我想这一切都将如我所愿般结束,
Ooh-ooh-ooh,
It would end like this,
一切都将如愿而终,
Ooh-ooh-ooh,
It would end like this,
一切都将如愿而终,
Ooh-ooh-ooh,
It would end like this,
一切都将如愿而终,
Ooh-ooh-ooh,
It would end like this,
一切都将如愿而终,
In my heart I knew it we'd end up here,
我心里明白 我们终究会抵达这里,
Walking through the ruins,
穿行在废墟之间,
But there's no tears on my face,
但我的脸上丝毫没有泪水,
I know it's too late to try and tempt fate,
我知道 我已经来不及去改变命运,
As if I could, I'll never hold back,
如果可以 我不会再隐瞒什么,
I know you know that you always understood,
毕竟这些 你我都心知肚明。
posted @ 2022-09-23 18:00  La_pluma  阅读(43)  评论(6编辑  收藏  举报