http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4345
思路: 状态dp ,用dp[j]表示达到状态j时的最大期望,转移方程为: dp[j] = dp[jj] + pp ,pp为第i题答对的概率(也即是第i题答对的期望)。
代码:
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
const double eps = 1e-8;
int T ,N;
double p[11][11] ;
double MAX(double a ,double b){
return a > b ? a: b ;
}
double dp[1<<10] ;
string pre[1<<10] ;
void DP(){
int MA = (1 << N) ;
for(int i=1;i<MA;i++)
dp[i] = -1 ; //浮点型最好不要用memset
dp[0] = 0 ;
pre[0]="";
for(int j=1;j<MA;j++){
for(int i=1;i<=N;i++){
if( (j&(1<<(i-1))) == 0 ) continue ;
double pp = p[i][i] ;
int jj = (j^(1<<(i-1))) ;
for(int k=1;k<=N;k++){
if( (jj&(1<<(k-1))) == 0) continue ;
pp = MAX(pp , p[k][i]);
}
pp += dp[jj] ;
if(pp>dp[j]+eps){
dp[j] = pp ;
pre[j] = pre[jj] ;
pre[j] += 'A'+i-1 ;
}
else if(pp > dp[j] - eps){
string s = pre[jj] ;
s += 'A'+i-1 ;
if(s < pre[j]) pre[j] = s ;
}
}
}
printf("%.2lf\n%s\n",dp[MA-1],pre[MA-1].c_str());
}
int main(){
double a ;
scanf("%d",&T);
for(int cas=1;cas<=T;cas++){
scanf("%d",&N);
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++){
scanf("%lf",&a);
p[i][j] = a / 100 ;
}
DP();
}
return 0 ;
}