您的位置:首页 > 其它

[NOIP模拟题]最佳旅行

2017-10-24 15:55 190 查看
Description

Bsny在杭州旅行,想去N个景点,于是他找来N个导游,每个导游负责带Bsny去一个景点玩一天,因此需要N个导游。这个N个导游对于N个景点有不同的熟悉度和喜爱度。为了旅游愉快,Bsny想尽量让每个导游可以去熟悉度和喜爱度最高的景点,但显然无法满足所有导游,因为Bsny希望想一种方案,使得每个导游的熟悉度总和与喜爱度总和之

积最大。你能告诉他最大能达到多少吗?

Input

第一行一个数N。

接下来一个N∗N的矩阵,其中元素Fi,j代表导游i对景点j的熟悉度。

接下来一个N∗N的矩阵,其中元素Li,j代表导游i对景点j的喜爱度。

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个景点的状态为S的最大熟悉度之和,gi,S表示选择了i个景点的状态为S的最大喜爱度之和,如果当前选择的熟悉度之和为sumx,喜爱度之和为sumy,最终答案为ans,那么(sumx+fi,S)∗(sumy+gi,S)>=ans才可能更新答案,这样剪枝所得到的时间复杂度很低了。

代码

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: