PART1: 校门外的树
Problem
某校大门外长度为 L 的马路上有一排树,每两棵相邻的树之间的间隔都是 1 米。我们可以把马路看成一个数轴,马路的一端在数轴 0 的位置,另一端在 L 的位置;数轴上的每个整数点,即 0,1,2,……,L,都种有一棵树。
由于马路上有一些区域要用来建地铁。这些区域用它们在数轴上的起始点和终止点表示。已知任一区域的起始点和终止点的坐标都是整数,区域之间可能有重合的部分。现在要把这些区域中的树(包括区域端点处的两棵树)移走。你的任务是计算将这些树都移走后,马路上还有多少棵树。
Input
输入的第一行有两个整数 L(1 <= L <= 10000)和 M(1 <= M <= 100),L 代表马路的长度,M 代表区域的数目,L 和 M 之间用一个空格隔开。接下来的 M 行每行包含两个不同的整数,用一个空格隔开,表示一个区域的起始点和终止点的坐标。
Output
输出包括一行,这一行只包含一个整数,表示马路上剩余的树的数目。
Sample Input
500 3 150 300 100 200 470 471
Sample Output
298
[note]
第一种方法比较直观: 设置一个 L 长的标志数组,每读入一个区域就将标志该区域部分的数组。
读完后将没有被标志的部分计数即可。
第二种方法: 按照区域的起始点从小到大排序,然后合并这些区域,最后再计数即可。
代码比较简单就不罗列了。
[/note]
PART2: 采药
Problem
辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”
如果你是辰辰,你能完成这个任务吗?
Input
输入的第一行有两个整数 T(1 <= T <= 1000)和 M(1 <= M <= 100),用一个空格隔开,T 代表总共能够用来采药的时间,M 代表山洞里的草药的数目。接下来的 M 行每行包括两个在 1 到 100 之间(包括 1 和 100)的整数,分别表示采摘某株草药的时间和这株草药的价值。
Output
输出包括一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。
Sample Input
70 3
71 100
69 1
1 2
Sample Output
3
[note]
DP,又见 DP。
使用 value[i][j] 表示采 [begin..i] 这些药物,以及 j 时间限制下所能达到的最大价值。
最后输出 value[M][T] 即可(M 和 T 的含义见题意)
[/note]
#define row 101 #define col 1001 #include<iostream> using namespace std; int t[101],v[101]; int T,M; int value[row][col]; void makeup(int time,int n) { for(int i=1;i<=n;i++) for(int j=1;j=time;j++) { value[i][j]=value[i-1][j]; int temp=value[i-1][j-t[i]]+v[i]; if(t[i]<=j&&temp>value[i-1][j]) value[i][j]=temp; } } int main() { scanf("{5f7b659ff3b2818cd787bc9e2e970b98d3e4ece1905bf98c409dc266242d6105}d{5f7b659ff3b2818cd787bc9e2e970b98d3e4ece1905bf98c409dc266242d6105}d",&T,&M); for(int i=M;i>0;i--) { scanf("{5f7b659ff3b2818cd787bc9e2e970b98d3e4ece1905bf98c409dc266242d6105}d{5f7b659ff3b2818cd787bc9e2e970b98d3e4ece1905bf98c409dc266242d6105}d",&t[i],&v[i]); } memset(value,0,row*col*sizeof(int)); makeup(T,M); printf("{5f7b659ff3b2818cd787bc9e2e970b98d3e4ece1905bf98c409dc266242d6105}dn",value[M][T]); return 0; } |