1. 程式人生 > >【bf】洛谷 P1850 換教室 暴力

【bf】洛谷 P1850 換教室 暴力

一、題目:

洛谷原題

二、思路:

爆搜。
暴力列舉要換的教室,計算期望值,不斷更新答案。
我寫了兩個DFS函式。第一個用來列舉換的教室,第二個用來算期望值,寫的很醜,望見諒。
得分:80分。233

三、補充:

補充一下遞迴實現指數型列舉的模板。

這等價於每個整數可以選或不選,所有可能的方案總數共有2n種。

vector<int>chosen;
inline void calc(int x){
    if(x==n+1){
        for(register int i=0;i<chosen.size();i++){
            printf
("%d",chosen[i]); } puts(""); return; } calc(x+1); chosen.push_back(x); calc(x+1); chosen.pop_back(); }

三、程式碼:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<set>
#include<vector>
#define eps 1e-8 using namespace std; inline int read(void) { int x = 0, f = 1; char ch = getchar(); while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); } while (ch >= '0'&&ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return
f * x; } const int maxn = 2005, maxv = 305; const double inf = (double)0x3f3f3f; int n, m, V, E, c[maxn], d[maxn], dis[maxv][maxv], v[maxn], cnt; double K[maxn], ans = inf; bool chosen[maxn]; inline void dfs2(int now,double &qiwang) { if (now == cnt + 1) { int dist = 0; for (register int i = 2; i <= n; i++) { if (chosen[i - 1]) { if (chosen[i]) { dist += dis[d[i]][d[i - 1]]; } else { dist += dis[c[i]][d[i - 1]]; } } else { if (chosen[i]) { dist += dis[d[i]][c[i - 1]]; } else { dist += dis[c[i]][c[i - 1]]; } } } double probability = 1.0; for (register int i = 1; i <= cnt; i++) { if (chosen[v[i]]) { probability *= K[v[i]]; probability += eps; } else { probability *= (1.0 - K[v[i]]); probability += eps; } } qiwang += (double)dist*probability; return; } dfs2(now + 1, qiwang); chosen[v[now]] = true; dfs2(now + 1, qiwang); chosen[v[now]] = false; } inline void dfs(int now) { if (now == n + 1 || cnt == m) { double temp = 0; dfs2(1, temp); ans = min(ans, temp); return; } dfs(now + 1); v[++cnt] = now; dfs(now + 1); cnt--; } inline void init(void) { n = read(); m = read(); V = read(); E = read(); m = min(n, m); for (register int i = 1; i <= n; i++) { c[i] = read(); } for (register int i = 1; i <= n; i++) { d[i] = read(); } for (register int i = 1; i <= n; i++) { scanf("%lf", &K[i]); } //floyd memset(dis, 0x3f, sizeof dis); for (register int i = 1; i <= V; i++)dis[i][i] = 0; for (register int i = 1; i <= E; i++) { int x = read(), y = read(), w = read(); dis[y][x] = dis[x][y] = min(dis[x][y], w); } for (register int k = 1; k <= V; k++) for (register int i = 1; i <= V; i++) for (register int j = 1; j <= V; j++) dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]); return; } inline void solve(void) { dfs(1); printf("%.2lf\n", ans); } int main() { init(); solve(); return 0; }