题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3502
题目大意:
对于n个题目每个题目答对的概率是之前答对的m道题r1,r2,r3....rm,取ar1r,ar2r,ar3r,...armr,arr的最大值
求一个序列是答对题的期望最大,并输出方案字典序最小的那个。
n只有10,考虑状压DP,对于结果比较好计算。。。跪在输出方案上了,用string记录转移过程。。。
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int s[15][15];
int n;
int f[2000];
string d[2000];
int ans=0;
int now;
int find(int x,int now)
{
int sum=-1;
for (int i=0;i<n;i++)
{
if (x&(1<<i))
{
sum=max(sum,s[i][now]);
}
}
return sum;
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
scanf("%d",&n);
for (int i=0;i<n;i++)
{
for (int j=0;j<n;j++)
{
scanf("%d",&s[i][j]);
}
}
f[0]=0;
d[0]="";
for (int x=1;x<(1<<n);x++)
{
f[x]=-1;
d[x]="";
for (int i=0;i<n;i++)
{
if (x&(1<<i))
{
now=f[x^(1<<i)]+find(x,i);
if (now>f[x] || (now==f[x] && d[x^(1<<i)]<d[x]))
{
f[x]=now;
d[x]=d[x^(1<<i)];
d[x]+=('A'+i);
}
}
}
}
ans=f[(1<<n)-1];
if (ans>=100)
{
printf("%d.",ans/100);
}
else
{
printf("0.");
}
ans%=100;
if (ans>=10)
{
printf("%d\n",ans);
}
else
{
printf("0%d\n",ans);
}
cout<<d[(1<<n)-1]<<endl;
}
return 0;
}