Pku acm 1160 post office 动态规划题目解题报告(十八)

http://acm.pku.edu.cn/JudgeOnline/problem?id=1160

题目给出m个村庄及其距离,给出n个邮局,要求怎么建n个邮局使代价最小。

思路:用opt[i][j]记录把前i个邮局建到前j个村庄中的最优解,用cost[i][j]记录所有在ij村庄中,建1个邮局的最小代价。显然邮局应该设到中点。让前i个邮局覆盖前j个村庄,第i+1个邮局覆盖第j+1j+k个村庄(j+k<=n),则状态转移方程为
opt[i+1][j+k]=min{opt[i][j]+cost[j+1][j+k];} (k+j<=n)

Cost数组存放从ij中有一个邮局的最小代价,显然该邮局应该放在中间,构造cost的代码和结果如下:

    for(i=1;i<=m;i++)

        for(j=i;j<=m;j++)

        {

            cost[i][j] = 0;

            mid = (i+j)/2;

            for(k=i;k<=j;k++)

                cost[i][j]+=(distance[mid]-distance[k])>=0 ?

distance[mid]-distance[k]:distance[k]-distance[mid];

        }

Cost[i][j]

1

2

3

4

5

6

7

8

9

10

1

0

1

2

6

10

16

21

37

74

117

2

 

0

1

4

8

11

16

31

68

109

3

 

 

0

3

4

7

11

26

61

102

4

 

 

 

0

1

3

7

20

55

94

5

 

 

 

 

0

2

4

17

50

89

6

 

 

 

 

 

0

2

13

46

74

7

 

 

 

 

 

 

0

11

33

61

8

 

 

 

 

 

 

 

0

22

28

9

 

 

 

 

 

 

 

 

0

6

10

 

 

 

 

 

 

 

 

 

0

 

Opt[i][j] 表示前i个邮局覆盖前j个村庄的最小代价,对于i=1来说,opt[i][j] = cost[i][j],让前2个邮局覆盖前j个村庄,也就是i=2的情况,可能是一下情况的最优解:第一个邮局覆盖第一个村庄,第二个村庄覆盖2-j个村庄,或者第一个邮局覆盖第1-2个村庄,第二个村庄覆盖3-j个村庄,第一个邮局覆盖第1-3个村庄,第二个村庄覆盖4-j个村庄,等等等等。该部分的代码如下:

for(i=0;i<=n;i++)

        for(j=0;j<=m;j++)

            if(opt[i][j]<3000000)

            {

                for(k=1;j+k<=m;k++)

                {

                    if(opt[i+1][j+k]>opt[i][j]+cost[j+1][j+k])

                    {

                        opt[i+1][j+k] = opt[i][j]+cost[j+1][j+k];

                    }

                }

            }

 

Opt[i][j]

0

1

2

3

4

5

6

7

8

9

10

0

0

 

 

 

 

 

 

 

 

 

 

1

 

0

1

2

6

10

16

21

37

74

117

2

 

 

0

1

4

8->5

11->8

16->12

31->27

68->62

109->103

3

 

 

 

 

 

 

 

 

 

 

 

4

 

 

 

 

 

 

 

 

 

 

 

5

 

 

 

 

 

 

 

 

 

 

 

带有详细注释的代码可以在http://download.csdn.net/user/china8848/获得

 
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值