必威-必威-欢迎您

必威,必威官网企业自成立以来,以策略先行,经营致胜,管理为本的商,业推广理念,一步一个脚印发展成为同类企业中经营范围最广,在行业内颇具影响力的企业。

      题目描述 Description,题目描述 Description

2019-09-27 22:08 来源:未知

3122 奶牛代理商 VIII

时间限制: 3 s 空间限制: 256000 KB 题目等级 : 大师 Master 题目描述 Description

小徐是USACO中国区的奶牛代理商,专门出售质优价廉的“FJ"牌奶牛。

有一天,她的奶牛卖完了,她得去美国进货。

她需要去N个奶牛农场询问价格(小徐是个认真的人,买东西一定要货比三家)。

给你一个邻接矩阵,表示N个农场间的路径长度,求小徐最少走多少路。(从农场1出发,最后回到出发点买)

输入描述 Input Description

N

邻接矩阵

输出描述 Output Description

答案

样例输入 Sample Input

3

0 1 2

3 0 10

2 0 0

样例输出 Sample Output

5

数据范围及提示 Data Size & Hint

N<=15,路径长度<=1000

TSP

分类标签 Tags 点此展开

 

状压DP好恶心啊。。

这道题的关键点有两个,

1.走过所有的点

2.最短路径

第2个最短路径比较好解决,n<=16的话,,一遍Floyd就可以

但是第一个条件,要走过所有的点。

我们可以考虑用状态压缩的方法来实现

我们可以用一个二进制的字符串表示这个点是否走过,比如说110表示已经走过了1和2这两个点,第3个点还没有经过

代码思路:

设置一个dp数组,dp[now][j]表示在now状态下,到达点j所需要的花费

首先我们需要暴力枚举i和j两点,来求最短距离

其次,我们还需要枚举一个能够包揽所有状态的变量now,来记录每一个能够到达的状态

当状态now可以到达j的话,那么说明我们可以通过这个状态到达i(i和j之间必定有路径)

最后枚举每个点,取一下最小值就可以

 

细节问题:

1.跑floyd的时候不要预先设定最大值,因为每两个点(不相同)之间必定有边相连

2.dp数组的第一位必须要开的足够大,最小是2^16,因为第一维记录的是状态而不是大小

3.now<=(1<<n)-1:

  当n==3时,1<<3 == 2^3 == 8 == 1000 

  1000-1=111正好是三个点都到达的理想情况

4.now&(1<<(j-1))

  j-1是为了不超边界且枚举出所有情况

  首先要明确,1<<(j-1)得到的一定是一个2^x的数,转换成二进制一定是1+000.....的形式

  那么当now&(1<<(j-1))有值时,就说状态now是可以到达j点的

5.now|(1<<(i-1))

  在进行这个运算的时候,now一定是满足now&(1<<(j-1))!=0的(程序满足顺序执行)

  那么通过now状态一定可以到达j点

  而且1<<(i-1)也一定是一个2^x的数

  所以now|(1<<(i-1))就是一个可以通过j到达i产生的新状态

 举个栗子:

 now=110010

 i=100

 那么结果就是110110

 

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 using namespace std;
 6 const int MAXN=30;
 7 int read(int & n)
 8 {
 9     char p='+';int x=0;
10     while(p<'0'||p>'9')
11         p=getchar();
12     while(p>='0'&&p<='9')
13     x=x*10+p-48,p=getchar();
14     n=x;
15 }
16 int dp[MAXN*2000][MAXN];
17 int dis[MAXN][MAXN];
18 int n;
19 void floyed()
20 {
21     for(int i=1;i<=n;i++)
22         for(int j=1;j<=n;j++)
23             for(int k=1;k<=n;k++)
24                 if(i!=j&&j!=k&&i!=k)
25                     dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
26 }
27 void zhuangya()
28 {
29     /*for(int i=1;i<=n;i++)
30     {
31         for(int j=1;j<=n;j++)
32         {
33             cout<<dis[i][j]<<" ";
34         }
35         cout<<endl;
36     }*/
37     memset(dp,0xf,sizeof(dp));
38     dp[1][1]=0;
39     for(int now=0;now<=(1<<n)-1;now++)
40         for(int i=1;i<=n;i++)
41             for(int j=1;j<=n;j++)
42                 if((now&(1<<(j-1)))&&i!=j)
43                 {
44                     dp[now|(1<<(i-1))][i]=
45                         min
46                         (
47                             dp[now|(1<<(i-1))][i],
48                             dp[now][j]+dis[j][i]
49                         );
50                 }
51     int ans=0x7ffffff;
52     for(int i=2;i<=n;i++)
53     {
54         ans=min(ans,dp[(1<<n)-1][i]+dis[i][1]);
55     }
56     cout<<ans;
57 }
58 int main()
59 {
60     read(n);
61     for(int i=1;i<=n;i++)
62         for(int j=1;j<=n;j++)
63             read(dis[i][j]);
64     floyed();
65     zhuangya();
66     return 0;
67 }

 

奶牛代理商 VIII,3122viii 3122 奶牛代理商 VIII 时间限制: 3 s 空间限制: 256000 KB 题目等级 : 大师 Master 题目描述 Description 小徐是USACO中国区...

3122 奶牛代理商 VIII

 

 时间限制: 3 s

 空间限制: 256000 KB

 题目等级 : 大师 Master

 

 

题目描述 Description

小徐是USACO中国区的奶牛代理商,专门出售质优价廉的“FJ"牌奶牛。

有一天,她的奶牛卖完了,她得去美国进货。

她需要去N个奶牛农场询问价格(小徐是个认真的人,买东西一定要货比三家)。

给你一个邻接矩阵,表示N个农场间的路径长度,求小徐最少走多少路。(从农场1出发,最后回到出发点买)

输入描述 Input Description

N

邻接矩阵

输出描述 Output Description

答案(见描述)

样例输入 Sample Input

3

0 1 2

3 0 10

2 0 0

 

样例输出 Sample Output

5

数据范围及提示 Data Size & Hint

N<=15,路径长度<=1000

TSP

 对于每一个城市只有去过和没去过两种状态,用一个二进制数s来表示
 f[s][i]当前在第i个城市,状态为s时的最小花费,&运算有0落0,所以s&1<<(j-1)保证了
 i城市的s状态 |运算有1落1 这样便可以找到一个从j到i的状态,用于更新答案

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 int mp[20][20];
 6 int f[70010][20];
 7 int n,ans = 1e9;
 8 void floyd()
 9 {
10     for (int k=1; k<=n; ++k)
11         for (int i=1; i<=n; ++i)
12             for (int j=1; j<=n; ++j)
13                 if (i!=j&&k!=i)
14                     mp[i][j] = min(mp[i][j],mp[i][k]+mp[k][j]);
15 }
16 void dp()
17 {
18     memset(f,0x3f,sizeof(f));
19     f[1][1] = 0;
20     for (int s=0; s<=(1<<n)-1; s++)
21         for (int i=1; i<=n; i++)
22         {
23             for (int j=1; j<=n; j++)
24                 if (s&1<<(j-1)&&i!=j)
25                     f[s|(1<<i-1)][i] = min(f[s|(1<<i-1)][i],f[s][j]+mp[j][i]);
26         }
27     for(int i=2; i<=n; i++) 
28         ans = min(ans,f[(1<<n)-1][i]+mp[i][1]);
29 }
30 int main()
31 {
32     scanf("%d",&n);
33     for (int i=1; i<=n; ++i)
34         for (int j=1; j<=n; ++j)
35             scanf("%d",&mp[i][j]);
36     floyd();
37     dp();
38     printf("%d",ans);
39     return 0;
40 }

 

3122 奶牛代理商 VIII
时间限制: 3 s
空间限制: 256000 KB
题目等级 : 大师 Master
题目描述 Description
小徐是USACO中国区的奶牛代理商,专门出售质优价廉的“FJ”牌奶牛。
有一天,她的奶牛卖完了,她得去美国进货。
她需要去N个奶牛农场询问价格(小徐是个认真的人,买东西一定要货比三家)。
给你一个邻接矩阵,表示N个农场间的路径长度,求小徐最少走多少路。(从农场1出发,最后回到出发点买)
输入描述 Input Description
N
邻接矩阵
输出描述 Output Description
答案(见描述)
样例输入 Sample Input
3
0 1 2
3 0 10
2 0 0
样例输出 Sample Output
5
数据范围及提示 Data Size & Hint
N<=15,路径长度<=1000
TSP
分类标签 Tags
动态规划 状态压缩型DP

TAG标签:
版权声明:本文由必威发布于必威-编程,转载请注明出处:      题目描述 Description,题目描述 Description