Description
Bsny在杭州旅行,想去
N
个景点,于是他找来
积最大。你能告诉他最大能达到多少吗?
Input
第一行一个数
接下来一个
N∗N
的矩阵,其中元素
Fi,j
代表导游
i
对景点
接下来一个
N∗N
的矩阵,其中元素
Li,j
代表导游
i
对景点
N<=17
,
1<=Fi,j,Li,j<=1,000
Output
仅一行表示最大的熟悉度总和与喜爱度总和之积。
Sample Input
3
1 2 3
2 3 1
3 1 2
1 2 3
2 3 1
3 1 2
Sample Output
81
样例解释
1导游选择3景点,2导游选择2景点,3导游选择1景点。
于是熟悉度之和为(3+3+3)=9, 喜爱度之和为(3+3+3)=9, 积为9*9=81 这个是最大方案。
HINT
思路
这道题的数据范围很小,一定是搜索。但是一般的搜索会TLE,那么要想一些优化措施了,令
fi,S
表示选择了
i
个景点的状态为
代码
#include <cstdio>
#include <algorithm>
const int maxn=17;
int n,f[maxn+2][1<<maxn],g[maxn+2][1<<maxn],ans;
int x[maxn+1][maxn+1],y[maxn+1][maxn+1];
int dfs(int now,int s,int sumx,int sumy)
{
if(now>n)
{
ans=std::max(ans,sumx*sumy);
return 0;
}
if((f[now][s]+sumx)*(g[now][s]+sumy)<ans)
{
return 0;
}
for(int i=1; i<=n; i++)
{
if(!(s&1<<(i-1)))
{
dfs(now+1,s|1<<(i-1),sumx+x[now][i],sumy+y[now][i]);
}
}
return 0;
}
int main()
{
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
scanf("%d",&x[i][j]);
}
}
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
scanf("%d",&y[i][j]);
}
}
for(int i=n; i>0; i--)
{
for(int j=0; j<1<<n; j++)
{
for(int k=1; k<=n; k++)
{
if(!(j&(1<<(k-1))))
{
f[i][j]=std::max(f[i][j],f[i+1][j|(1<<(k-1))]+x[i][k]);
g[i][j]=std::max(g[i][j],g[i+1][j|(1<<(k-1))]+y[i][k]);
}
}
}
}
dfs(1,0,0,0);
printf("%d\n",ans);
return 0;
}