zoukankan      html  css  js  c++  java
  • Codeforces 678E Another Sith Tournament 状压DP

    题意:

    (n(n leq 18))个人打擂台赛,编号从(1)(n),主角是(1)号。
    一开始主角先选一个擂主,和一个打擂的人。
    两个人之中胜的人留下来当擂主等主角决定下一个人打擂,败的人退出比赛,直到比赛只剩一个人。
    已知任意两人之间决胜的胜率(P_{ij}),求主角最终能够获胜的概率。

    分析:

    (d(S, i))表示存活的人的集合为(S),当前擂主为(i in S),主角获胜的概率。
    为了方便我们把编号设为(0 sim n-1),递推边界(d(1,0)=1)

    考虑(d(S,i)),枚举下一个要打擂的人(k in S)

    • (P_{ij})的概率(i)战胜(j),擂主为(i),状态转移到(d(S-j,i))
    • (P_{ji})的概率(j)战胜(i),擂主为(j),状态转移到(d(S-i,j))

    因为主角可以决定打擂人选(j),所以(d(S,i)=max{ P_{ij}d(S-j,i) + P_{ji}d(S-i,j) })

    最后枚举最开始的擂主,选一个最大值就是答案。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    double p[18][18], d[1 << 18][18];
    
    int main()
    {
    	int n; scanf("%d", &n);
    	for(int i = 0; i < n; i++)
    		for(int j = 0; j < n; j++) scanf("%lf", &p[i][j]);
    
    	d[1][0] = 1;
    	for(int S = 3; S < (1 << n); S += 2) {
    		for(int i = 0; i < n; i++) if(S&(1<<i)) {
    			for(int j = 0; j < n; j++) if(j != i && (S&(1<<j))) {
    				d[S][i] = max(d[S][i], p[i][j]*d[S^(1<<j)][i] + p[j][i]*d[S^(1<<i)][j]);
    			}
    		}
    	}
    
    	double ans = 0;
    	for(int i = 0; i < n; i++) ans = max(ans, d[(1<<n)-1][i]);
    
    	printf("%.15f
    ", ans);
    
    	return 0;
    }
    
  • 相关阅读:
    Jmeter性能测试--自己看到的博客收集
    python日志logging
    java学习day12--API-File文件流
    java学习day12--API-IO简介--流简介
    java学习day12--API-SimpleDateFormat--BigDecimal/BigInteger类
    java学习day12--API-包装类-Date类
    equals方法和 == 的使用
    java学习day11--API--Object类-String类-StringBuilder类
    构造方法和普通方法的区别
    java中的修饰符总结
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/5587523.html
Copyright © 2011-2022 走看看