码迷,mamicode.com
首页 > 其他好文 > 详细

观光游览

时间:2016-08-20 21:51:53      阅读:252      评论:0      收藏:0      [点我收藏+]

标签:

一条街道被分成m格(1<=m<=100),还有n个景点(1<=n<=100),分布在街道上。每个景点可以占据连续的若干格,并且有一个美学值v(0<v<=100)。现要组织k个人考察这个街道(1<=k<=m),每个人考察的区域是连续的若干格(不可为0格),且任意两个人考察的区域不得相交,也不得有一个格子无人考察。对于任意一个人,如果它考察的区域中有一个风景点(风景点必须完整的位于这个区域),则它就得到了这个风景点的分值(美学值)。
    你的任务是将街道的m个格子分给k个人去考察,使得总的分值最大。

输入格式
    第一行一个整数m,表示街道的长度。
    第二行一个整数n,表示风景点个数。
    此后n行,每行描述一个风景点,三个整数x、y和v,表示该风景点是从第x个格子到第y个格子,美学值为v。
    最后一行一个整数k,表示考察的人数。

输出格式
    一个整数,表示最大可以得到的分值。

样例输入
3
2
1 2 2
2 3 3
2

样例输出
3

 

首先我们定义一个g[i][j]表示选i到j段能得到的最大价值,预处理一下就行了,然而如果直接预处理是n^3的时间复杂度,虽然这道题n^3可以过,但可以优化到n^2,等会说。

然后在定义一个f[i][j]表示将前i个分成j份能得到的最大价值,

于是f[i][j]=max(f[x][j-1]+g[x+1][i])(0<=x<i).

再来说说怎么将预处理优化到n^2,这就要用到容斥原理了,

这道题只需用到这个公式:A∪B = A+B - A∩B

举个简单的例子,就是有a个人喜欢足球,b个人喜欢篮球,c个人既喜欢足球,有喜欢篮球,那么总人数=a+b-c;

那么这道题也是这样:g[x][y]=g[x+1][y]+g[x][y-1]-g[x+1][y-1];

代码参上:

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <conio.h>
 6 #include <cstdio>
 7 #include <cmath>
 8 using namespace std;
 9 
10 int len,cnt,k,ks[105],js[105],v[105],g[105][105],f[105][105];
11 
12 int main(){
13     scanf("%d%d",&len,&cnt);    
14     for(int x=1;x<=cnt;x++){
15         scanf("%d%d%d",ks+x,js+x,v+x);
16         g[ks[x]][js[x]]+=v[x];
17     }
18     scanf("%d",&k);
19     for (int y=2; y<=len;y++)
20         for(int x=1;x<=len;x++)
21             g[x][x+y-1]+=g[x][x+y-2]+g[x+1][x+y-1]-g[x+1][x+y-2];
22     memset(f,-127/2,sizeof(f));
23     f[0][0]=0;        
24     for(int x=1;x<=k;x++){
25         for(int y=1;y<=len;y++){
26             for(int i=0;i<y;i++){
27                 f[y][x]=max(f[y][x],f[i][x-1]+g[i+1][y]);
28             }
29         }
30     }
31     printf("%d",f[len][k]);
32     return 0;
33 }

 

观光游览

标签:

原文地址:http://www.cnblogs.com/Ateisti/p/5791230.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!