zoukankan      html  css  js  c++  java
  • 洛谷刷题记录(一)【入门】

    P2036 [COCI2008-2009#2] PERKET

    题目描述

    Perket 是一种流行的美食。为了做好 Perket,厨师们必须小心选择配料,以便达到更好的口感。你有N种可支配的配料。对于每一种配料,我们知道它们各自的酸度 S 和甜度 B。当我们添加配料时,总的酸度为每一种配料的酸度总乘积;总的甜度为每一种配料的甜度的总和。

    众所周知,美食应该口感适中;所以我们希望选取配料,以使得酸度和甜度的绝对差最小。

    另外,我们必须添加至少一种配料,因为没有美食是以白水为主要配料的。

    输入格式

    第一行包括整数 N,表示可支配的配料数。
    接下来 N 行,每一行为用空格隔开的两个整数,表示每一种配料的酸度和甜度。
    输入数据保证,如果我们添加所有配料,总的酸度和甜度都不会超过 (10^9)

    输出格式

    输出酸度和甜度的最小的绝对差。

    输入输出样例

    输入 #1

    1
    3 10

    输出 #1

    7

    输入 #2

    4
    1 7
    2 6
    3 8
    4 9

    输出 #2

    1

    说明/提示

    (1 le N le 10.)

    我的思路

    本题搜索最小值,可用深度优先搜索(DFS)解题。

    首先选择一个入口,即第一组选择的调料(这个入口从第一组到最后一组遍历进入dfs模块,记住这个入口点,如果是第一次记得初始化最小值);接着再编写dfs函数,分两种情况:一种普通情况继续搜索,即在之前的选择上继续选择,并且每一次选择后都要计算总酸度与总甜度之差,如果小于我们记录的最小值则更新,完了返回来的时候再将酸度和甜度修改回去,继续遍历。二是选择到最后一组调料了,这时候搜索到头了,直接RETURN结束这次搜索。

    注意我们的搜索是从前往后按顺序来的,这样可以避免重复。

    AC代码

    #include<stdio.h>
    int s[10], b[10];
    int n;
    long ans;  //最后结果 
    
    void dfs(long mul, long sum, int start){
    	if(start==n-1){  //每次到最后一组调料就结束 
    		return;
    	}
    	else{
    		for(int i=start+1; i<n; i++){  //从前往后选调料,避免重复 
    			mul *= s[i];
    			sum += b[i];
    			long tmp = mul-sum>0?mul-sum:sum-mul;
    			if(tmp < ans) ans = tmp;
    			dfs(mul, sum, i);  //递归进行叠加选择 
    			mul /= s[i];       //恢复当前总酸度和总甜度,以便进行下一次选择 
    			sum -= b[i];
    		}
    	}
    }
    
    int main(){
    	scanf("%d", &n);
    	for(int i=0; i<n; i++){
    		scanf("%d%d", &s[i], &b[i]);
    	}
    	for(int i=0; i<n; i++){  //选择开始第一种配料开始遍历搜索 
    		long mul = s[i];
    		long sum = b[i];
    		long tmp = mul-sum>0?mul-sum:sum-mul;
    		if(i==0 || tmp<ans) ans = tmp;
    		dfs(mul, sum, i);
    	}
    	printf("%ld", ans);
    	
    	return 0;
    }
    

    ---2020/7/27---


    P2676 [USACO07DEC]Bookshelf B

    题目描述

    Farmer John最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此的大,但它还是几乎瞬间就被各种各样的书塞满了。现在,只有书架的顶上还留有一点空间。

    所有N(1 <= N <= 20,000)头奶牛都有一个确定的身高H_i(1 <= H_i <= 10,000)。设所有奶牛身高的和为S。书架的高度为B,并且保证 1 <= B <= S < 2,000,000,007。

    为了够到比最高的那头奶牛还要高的书架顶,奶牛们不得不像演杂技一般,一头站在另一头的背上,叠成一座“奶牛塔”。当然,这个塔的高度,就是塔中所有奶牛的身高之和。为了往书架顶上放东西,所有奶牛的身高和必须不小于书架的高度。

    显然,塔中的奶牛数目越多,整座塔就越不稳定,于是奶牛们希望在能够到书架顶的前提下,让塔中奶牛的数目尽量少。 现在,奶牛们找到了你,希望你帮她们计算这个最小的数目。

    输入格式

    第1行: 2个用空格隔开的整数:N 和 B * 第2..N+1行: 第i+1行是1个整数:H_i

    输出格式

    第1行: 输出1个整数,即最少要多少头奶牛叠成塔,才能够到书架顶部

    输入输出样例

    输入 #1

    6 40
    6
    18
    11
    13
    19
    11

    输出 #1

    3

    说明/提示

    输入说明:

    一共有6头奶牛,书架的高度为40,奶牛们的身高在6..19之间。

    输出说明:

    一种只用3头奶牛就达到高度40的方法:18+11+13。当然还有其他方法,在此不一一列出了。

    我的思路

    显然我们最容易想到的思路就是将奶牛的身高从大到小排序,循环减去奶牛身高并计数,得出最终答案。

    考虑到奶牛数量,我们可以选择排序较快的算法,这时我们想到C++的STL里的sort函数,当然它并不一定是快速排序,它会根据实际数量来选择更优的排序算法,这也恰好满足了我们的需要。

    AC代码

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int n,h[20005], ans;
    long s, b;
    
    bool cmp(int a, int b){
    	return a>b;
    } 
    
    int main(){
    	scanf("%d%d", &n, &b);
    	for(int i=0; i<n; i++){
    		scanf("%d", &h[i]);
    	}
    	sort(h, h+n, cmp);
    	for(int i=0; b>0; i++){
    		b = b - h[i];
    		ans++;
    	}
    	printf("%d", ans);
    	
    	return 0;
    }
    

    ---2020/7/28---


    P1116 车厢重组

    题目描述

    在一个旧式的火车站旁边有一座桥,其桥面可以绕河中心的桥墩水平旋转。一个车站的职工发现桥的长度最多能容纳两节车厢,如果将桥旋转180180度,则可以把相邻两节车厢的位置交换,用这种方法可以重新排列车厢的顺序。于是他就负责用这座桥将进站的车厢按车厢号从小到大排列。他退休后,火车站决定将这一工作自动化,其中一项重要的工作是编一个程序,输入初始的车厢顺序,计算最少用多少步就能将车厢排序。

    输入格式

    共两行。

    第一行是车厢总数N( (le) 10000)。

    第二行是N个不同的数表示初始的车厢顺序。

    输出格式

    一个整数,最少的旋转次数。

    输入输出样例

    输入 #1

    4
    4 3 2 1

    输出 #1

    6

    我的思路

    相邻两数交换位置,使得最终结果从小到大排序,仔细一想,这不就是冒泡排序么?!

    AC代码

    #include<stdio.h>
    int n, len[10005], ans;
    int main(){
    	scanf("%d", &n);
    	for(int i=0; i<n; i++){
    		scanf("%d", &len[i]);
    	}
    	for(int i=0; i<n-1; i++){  // 每次循环都有一个最大值“冒泡”到最后,n-1次后剩下1个最小的不必排 
    		for(int j=0; j<n-i-1; j++){  // 每次冒泡只需到未排序区,“已冒出的泡”无需再排 
    			if(len[j] > len[j+1]){  // 相邻比较,大者后移 
    				int tmp = len[j];
    				len[j] = len[j+1];
    				len[j+1] = tmp;
    				ans++;
    			}
    		}
    	}
    	printf("%d", ans);
    	
    	return 0;
    }
    

    ---2020/7/29---


    P2956 [USACO09OCT]The Robot Plow G

    题目描述

    Farmer John has purchased a new robotic plow in order to relieve him from the drudgery of plowing field after field after field. It achieves this goal but at a slight disadvantage: the robotic plow can only plow in a perfect rectangle with sides of integer length.

    Because FJ's field has trees and other obstacles, FJ sets up the plow to plow many different rectangles, which might end up overlapping. He's curious as to just how many squares in his field are actually plowed after he programs the plow with various plow instructions, each of which describes a rectangle by giving its lower left and upper right x,y coordinates.

    As usual, the field is partitioned into squares whose sides are parallel to the x and y axes. The field is X squares wide and Y squares high (1 <= X <= 240; 1 <= Y <= 240). Each of the I (1 <= I <= 200) plow instructions comprises four integers: Xll, Yll, Xur, and Yur (1 <= Xll <= Xur; Xll <= Xur <= X; 1 <= Yll <= Yur; Yll <= Yur <= Y) which are the lower left and upper right coordinates of the rectangle to be plowed. The plow will plow all the field's squares in the range (Xll..Xur, Yll..Yur) which might be one more row and column than would initially be assumed (depending on how you go about your assumptions, of course).

    Consider a field that is 6 squares wide and 4 squares high. As FJ issues a pair of plowing instructions (shown), the field gets plowed as shown by '*' and '#' (normally plowed field all looks the same, but '#' shows which were most recently plowed):

    ......
    ......
    ......
    ......

    (1,1)(2,4)

    **....
    **....
    **....
    **....

    (1,3)(5,4)

    #####.
    #####.
    **....
    **....

    A total of 14 squares are plowed.

    POINTS: 25

    输入格式

    Line 1: Three space-separated integers: X, Y, and I

    输出格式

    Lines 2..I+1: Line i+1 contains plowing instruction i which is described by four integers: Xll, Yll, Xur, and Yur

    输入输出样例

    输入 #1

    6 4 2
    1 1 2 4
    1 3 5 4

    输出 #1

    14

    说明/提示

    As in the task's example.

    我的思路

    本题难点在于如何知道哪些格子重复了,一开始我思考怎么避免这一次的区域和上一次部分重合,但是这样也不能避免和所有之前所有的区域都避免重合,不说存储,光是判断就要浪费很多时间。

    后来我一拍大腿,这不就是统计有多少地从没耕到耕了的状态吗?!这样用一个bool数组记录就可,每次耕一块新地都计数,这个题目立即就简单的不得了!

    AC代码

    #include<cstdio>
    int x, y, n;
    long ans, xll, yll, xur, yur;
    bool mp[245][245]; 
    int main(){
    	scanf("%d%d%d", &x, &y, &n);
    	for(int i=0; i<n; i++){
    		scanf("%ld%ld%ld%ld", &xll, &yll, &xur, &yur);
    		for(int j=xll; j<=xur; j++){
    			for(int k=yll; k<=yur; k++){
    				if(!mp[j][k]){
    					mp[j][k] = true;
    					ans++;
    				}
    			}
    		}
    	}
    	printf("%ld", ans);
    	
    	return 0;
    }
    

    ---2020/7/30---


    P1830 轰炸III

    题目背景

    一个大小为N*M的城市遭到了X次轰炸,每次都炸了一个每条边都与边界平行的矩形。

    题目描述

    在轰炸后,有Y个关键点,指挥官想知道,它们有没有受到过轰炸,如果有,被炸了几次,最后一次是第几轮。

    输入格式

    第一行,四个整数:n、m、x、y。

    以下x行,每行四个整数:x1、y1、x2、y2,表示被轰炸的矩形的左上角坐标和右下角坐标(比如1 3 7 10就表示被轰炸的地方是从(1,3)到(7,10)的矩形)。

    再以下y行,每行两个整数,表示这个关键点的坐标。

    输出格式

    共y行,每行第一个字符为Y或N,表示是否被轰炸,若为Y,在一个空格后为两个整数,表示被炸了几次和最后一次是第几轮。

    输入输出样例

    输入 #1

    10 10 2 3
    1 1 5 5
    5 5 10 10
    3 2
    5 5
    7 1

    输出 #1

    Y 1 1
    Y 2 2
    N

    说明/提示

    数据很弱!!!直接模拟!!!!
    (1 le N,M le 100)

    我的思路

    题的思路和上一题差不多,不过将地图数组多开了一维,以记录需要输出的数据。

    AC代码

    #include<stdio.h>
    int n, m, x, y;
    int mp[105][105][2];  //记录轰炸次数 
    
    int main(){
    	scanf("%d%d%d%d", &n, &m, &x, &y);
    	int x1[x], y1[x], x2[x], y2[x], px[y], py[y];
    	for(int i=0; i<x; i++){
    		scanf("%d%d%d%d", &x1[i], &y1[i], &x2[i], &y2[i]);
    	}
    	for(int i=0; i<y; i++){
    		scanf("%d%d", &px[i], &py[i]);
    	}
    	//开始模拟轰炸 
    	for(int i=0; i<x; i++){
    		for(int j=x1[i]; j<=x2[i]; j++){
    			for(int k=y1[i]; k<=y2[i]; k++){
    				mp[j][k][0]++;		//记录轰炸次数 
    				mp[j][k][1] = i+1;  //记录最后一次轰炸是第几轮 
    			}
    		}
    	}
    	//模拟完毕
    	for(int i=0; i<y; i++){
    		int tx = px[i];
    		int ty = py[i];
    		if(mp[tx][ty][0] != 0){
    			printf("Y %d %d", mp[tx][ty][0], mp[tx][ty][1]);
    		}
    		else{
    			printf("N");	
    		}
    		if(i+1<y){
    			printf("
    ");  //防止最后一行多输回车 
    		}
    	} 
    	
    	return 0;
    }
    

    P1789 【Mc生存】插火把

    题目描述

    话说有一天 linyorson 在“我的世界”开了一个 (n imes n(nle 100)) 的方阵,现在他有 m 个火把和 k 个萤石,分别放在 ((x_1,y_1)...(x_m,y_m))((o_1,p_1)...(o_k,p_k)) 的位置,没有光或没放东西的地方会生成怪物。请问在这个方阵中有几个点会生成怪物?

    P.S.火把的照亮范围是:

        |暗|暗| 光 |暗|暗|
        |暗|光| 光 |光|暗|
        |光|光|火把|光|光|
        |暗|光| 光 |光|暗|
        |暗|暗| 光 |暗|暗|
    

    萤石:

        |光|光| 光 |光|光|
        |光|光| 光 |光|光|
        |光|光|萤石|光|光|
        |光|光| 光 |光|光|
        |光|光| 光 |光|光|
    

    输入格式

    输入共m+k+1行。

    第一行为n,m,k。

    第2到第m+1行分别是火把的位置 (x_i, y_i)

    第m+2到第m+k+1行分别是萤石的位置 (o_i, p_i)

    注:可能没有萤石,但一定有火把。

    所有数据保证在int范围内。

    输出格式

    有几个点会生出怪物。

    输入输出样例

    输入 #1

    5 1 0
    3 3

    输出 #1

    12

    我的思路

    本题可以模拟照亮地图的过程,计数照亮多少个单位,然后再用总面积减去照亮面积。

    火把照亮区域不规则,我一开始用的是循环3*3加上4个赋值语句,最后还搜了一整遍地图计答案,结果有两个测试样例超时了。

    下面的是经我修改后的第二版代码,减少了一些耗时,顺利通过。

    AC代码

    #include<cstdio>
    int n, m, k, ans;
    bool mp[105][105];
    int f[13][2] = {{0, -2}, {-1, -1}, {0, -1}, {1, -1}, 
    			 {-2, 0}, {-1, 0}, {0, 0}, {1, 0}, {2, 0},
    			 {-1, 1}, {0, 1}, {1, 1}, {0, 2}};
    			 
    bool in(int x, int y){
    	return 0<x && x<=n && 0<y && y<=n;
    }
    
    int main(){
    	scanf("%d%d%d", &n, &m, &k);
    	int fx, fy, sx, sy;  //fx, fy表示火把坐标;sx, sy表示萤石坐标 
    	//开始模拟照亮地图 
    	for(int i=0; i<m; i++){
    		scanf("%d%d", &fx, &fy);
    		for(int j=0; j<13; j++){
    			int x = fx + f[j][0];
    			int y = fy + f[j][1];
    			if(in(x, y)){
    				if(!mp[x][y]){
    					mp[x][y] = true;
    					ans++;
    				}
    			}
    		}
    	}
    	for(int i=0; i<k; i++){
    		scanf("%d%d", &sx, &sy);
    		for(int x=sx-2; x>0 && x<=sx+2 && x<=n; x++){
    			for(int y=sy-2; y>0 && y<=sy+2 && y<=n; y++){  //萤石范围 
    				if(!mp[x][y]){
    					mp[x][y] = true;
    					ans++;
    				}
    			}
    		}
    	}
    	//模拟结束,计算结果
    	ans = n*n - ans;
    
    	printf("%d", ans);
    	
    	return 0; 
    }
    

    ---2020/7/31---

  • 相关阅读:
    引擎设计跟踪(一)
    Gamebyro 加入CEGUI
    开播庆祝
    引擎设计跟踪(八) Mile stone 2 准备中
    引擎设计跟踪(六)
    编辑器框架的思考
    地形法线贴图的优化
    引擎设计跟踪(五)
    引擎设计跟踪(九.2) 3DS MAX 导出插件 继续
    引擎设计跟踪(三)
  • 原文地址:https://www.cnblogs.com/IvyzZ/p/13386691.html
Copyright © 2011-2022 走看看