• [2019南京网络赛D题]Robots


    题目链接

    2019.9.2更新


    第二天睡醒想了想发现好像搜一遍就可以过,赛时写的花里胡哨的还错了,太菜了QAQ

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn = 3e5 + 10;
     5 struct node {
     6     int s, e, next;
     7 }edge[maxn];
     8 int head[maxn], len;
     9 void init() {
    10     memset(head, -1, sizeof(head));
    11     len = 0;
    12 }
    13 void add(int s, int e) {
    14     edge[len].s = s;
    15     edge[len].e = e;
    16     edge[len].next = head[s];
    17     head[s] = len++;
    18 }
    19 double dp[maxn], dp2[maxn];
    20 int vis[maxn],n;
    21 void dfs(int x) {
    22     if (vis[x])
    23         return;
    24     vis[x] = 1;
    25     dp[x] = dp2[x] = 0;
    26     if (x == n)
    27         return;
    28     int num = 0;
    29     for (int i = head[x]; i != -1; i = edge[i].next) {
    30         int y = edge[i].e;
    31         dfs(y);
    32         dp[x] += dp[y];
    33         dp2[x] += dp2[y];
    34         num++;
    35     }
    36     dp[x] += num + 1, dp[x] /= num;
    37     dp2[x] += (num + 1)*dp[x], dp2[x] /= num;
    38 }
    39 int main() {
    40     int t;
    41     scanf("%d", &t);
    42     while (t--) {
    43         int  m, x, y;
    44         init();
    45         scanf("%d%d", &n, &m);
    46         for (int i = 1; i <= m; i++)
    47             scanf("%d%d", &x, &y), add(x, y);
    48         memset(vis, 0, sizeof(vis));
    49         dfs(1);
    50         printf("%.2f
    ", dp2[1]);
    51     }
    52 }

    原文


    绝望ing!!!

    搞了3个小时的D,到最后也没过,吃饭的时候突然想到错了,改一改就过了Orz.

    遗憾!!错在求了拓扑序,要用a[n]->a[1],结果用成了n->1。要被队友骂死了QAQ

    而且样例刚好1-n是拓扑序(


    题意是说,在DAG中从1到n,每次有x/(x+1)的概率到相连的点,1/(x+1)的概率原地不动,(x为相连的点的个数)。每次移动需要一天,每次移动会消耗当前天数数值那么多的能量,求到达n点的期望能量消耗。

    一开始就蛮有感觉的,DAG上跑期望dp,先跑期望天数,再跑期望能量,设dp[i]为i点到n点的期望天数,则初始dp[n]=0,转移为$dp[i]= frac{1}{x+1}*sum dp[j]+ frac{1}{x+1}*dp[i]+1$ i->j有边。

    然后再跑期望能量,dp2[i]为i到n点的期望能量,初始为dp2[n]=0,转移为$dp2[i]= frac{1}{x+1}*sum dp2[j]+ frac{1}{x+1}*dp2[i]+dp[i]$ i->j有边。

    代码极度丑陋,望见谅。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 4e5 + 10;
     4 struct node {
     5     int s, e, next;
     6 }edge[maxn], edge2[maxn];
     7 int head[maxn], head2[maxn], len, len2;
     8 void init() {
     9     memset(head, -1, sizeof(head));
    10     memset(head2, -1, sizeof(head2));
    11     len = len2 = 0;
    12 }
    13 void add(int s, int e) {
    14     edge[len].s = s;
    15     edge[len].e = e;
    16     edge[len].next = head[s];
    17     head[s] = len++;
    18 }
    19 void add2(int s, int e) {
    20     edge2[len2].s = s;
    21     edge2[len2].e = e;
    22     edge2[len2].next = head2[s];
    23     head2[s] = len2++;
    24 }
    25 double dp[maxn], dp2[maxn];
    26 int in[maxn], a[maxn], num[maxn];
    27 void solve(int n) {
    28     int lens = 0;
    29     queue<int>q;
    30     for (int i = 1; i <= n; i++)
    31         if (in[i] == 0) q.push(i);
    32     while (!q.empty()) {
    33         int p = q.front(); q.pop();
    34         a[++lens] = p;
    35         for (int i = head[p]; i != -1; i = edge[i].next) {
    36             int y = edge[i].e;
    37             in[y]--;
    38             if (in[y] == 0)
    39                 q.push(y);
    40         }
    41     }
    42 }
    43 int main() {
    44     int t;
    45     scanf("%d", &t);
    46     while (t--) {
    47         int n, m, x, y;
    48         scanf("%d%d", &n, &m);
    49         init();
    50         for (int i = 1; i <= n; i++)
    51             in[i] = 0, num[i] = 0, dp2[i] = dp[i] = 0;
    52         for (int i = 1; i <= m; i++)
    53             scanf("%d%d", &x, &y), add(x, y), add2(y, x), in[y]++;//正向反向各存一图,正向跑拓扑,反向求期望
    54         solve(n);//求拓扑序
    55         dp[a[n]] = 0;
    56         for (int x = n; x >= 1; x--) {//期望dp日常倒推
    57             if (a[x] != n) dp[a[x]] += num[a[x]] + 1, dp[a[x]] /= num[a[x]];//num[i]为与i点相连的点数
    58             num[a[x]] = 0;
    59             for (int i = head2[a[x]]; i != -1; i = edge2[i].next) {
    60                 int y = edge2[i].e;
    61                 dp[y] += dp[a[x]];
    62                 num[y]++;
    63             }
    64         }
    65         dp2[n] = 0;
    66         for (int x = n; x >= 1; x--) {
    67             if (a[x] != n) dp2[a[x]] += (num[a[x]] + 1) * dp[a[x]], dp2[a[x]] /= num[a[x]];
    68             for (int i = head2[a[x]]; i != -1; i = edge2[i].next) {
    69                 int y = edge2[i].e;
    70                 dp2[y] += dp2[a[x]];
    71                 num[y]++;
    72             }
    73         }
    74         printf("%.2lf
    ", dp2[1]);
    75     }
    76 }
  • 相关阅读:
    让android系统中任意一个view变成进度条
    AIDL(2):服务端回调客户端
    java 简单的des加密示例
    java中的集合:继承关系和简介
    java中的线程(4):常用同步类 CountDownLatch、CyclicBarrier和Semaphore
    java中的线程(3):线程池类 ThreadPoolExecutor「线程池的类型、参数、扩展等」
    java中的线程(2):如何正确停止线程之2种常见停止方式
    java中的线程(1):如何正确停止线程Why Are Thread.stop, Thread.suspend, Thread.resume and Runtime.runFinalizersOnExit Deprecated?
    android上最多有多少个http连接?
    采用MQTT协议实现android消息推送(4)选fusesource-mqtt-client为客户端
  • 原文地址:https://www.cnblogs.com/sainsist/p/11443200.html
Copyright © 2020-2023  润新知