狀態壓縮+概率dp
阿新 • • 發佈:2018-11-05
https://www.nowcoder.com/acm/contest/57/C
題目:小C現在要參加一場wannafly挑戰賽,一場挑戰賽一共有n道題,一共有m分鐘。對於第i道題,小C解決它需要恰好j分鐘的概率是pi,j。小C每次會選擇某一道沒做完的題,然後把它解決(不能中途放棄),之後再決策下一道要做的題是哪道。求小C在最優策略下,期望能做出幾道題。
思路:狀態壓縮+概率dp,E(期望)=∑XiPi。則:dp[i][j]表示狀態i下,j分鐘能做出期望題數,假設pre是i的前一個狀態,那麼有:dp[i][j]=∑(dp[pre][j-k]+1)p[i^pre][k]。
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.StreamTokenizer; import java.math.BigDecimal; public class Main { static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out)); static int nextInt() throws IOException { in.nextToken(); return (int)in.nval; } static double nextDouble() throws IOException { in.nextToken(); return (double)in.nval; } static String next() throws IOException { in.nextToken(); return (String)in.sval; } static double a[][] = new double[7][183]; static double dp[][] = new double[1 << 6][183]; public static void main(String[] arg) throws IOException { int n, m; n = nextInt(); m = nextInt(); double tmp; for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { a[i][j] = nextDouble(); } } for(int i = 1; i < (1 << n); i++) { // 不同方案 for(int j = 1; j <= m; j++) { // 列舉花費時間、 for(int k = 1; k <= n; k++) { // 當前這種方案都是使用了那道題目, if((i & (1 << (k - 1))) > 0) { // 用了題目 k tmp = 0; for(int zz = 1; zz <= j; zz++) { // 用zz分鐘做k題目 tmp += (1 + dp[i ^ (1 << (k - 1))][j - zz]) * a[k][zz]; // i ^ (1 << (k - 1))即未選擇k時的方案、這裡dp[i][j]計算的是期望 } dp[i][j] = Math.max(dp[i][j], tmp); } } } } BigDecimal bd = new BigDecimal(dp[(1 << n) - 1][m]).setScale(5, BigDecimal.ROUND_HALF_DOWN); out.println(bd); out.flush(); } }