第三届全国中医药院校大学生程序设计竞赛 (正式赛)

目录

 Problem B. 绿地装饰(暴力模拟+思维)

E 解密(水+有点巧妙的解法)

         F: 巍巍岳麓(类似最小生成树)

H: 百舸争流(贪心)


 

 Problem B. 绿地装饰(暴力模拟+思维)

时间限制: 1  内存限制: 128 MB

提交: 56  解决: 22  201501010119

提交状态讨论版

题目链接:http://acm.hnucm.edu.cn/JudgeOnline/problem.php?id=1366

题目描述

湖南中医药大学坐落于中国历史文化名城长沙,是湖南省重点建设本科院校,是全国首批设立国家级重
点学科的高校,也是首批招收博士研究生、留学生及港澳台学生的中医药院校。学校现有 2 个校区,占
地面积 1393 亩,建筑面积 52 万平方米,主校区依岳麓南坡,临湘江西岸,环境幽雅,风光秀丽,是求
学成才的理想之地。
校园景观设计师小 W 的主要工作就是植被环境的设计维护,他有一个 N×N 的模板图,他创作景观的步
骤如下:
1、将当前的绿地分成 N×N 小块,再按照模板图添加装饰(黑色表示有装饰,白色表示没有);
2、对于每个白色(未被装饰)的地块,递归操作 1,应用模板图,即分成更小的 N×N 块,继续进行装
饰,而黑色(已装饰)的地块则不必操作。

下图是某次装饰过程的示意图。

现在你的任务是求出 K 次递归后的绿地状态。

输入

单组数据。
第一行两个数 N,K,如题意中的描述。
接下来是一个 N×N 的模板图,’ . ’ 表示白色,’ * ’ 表示黑色。
2 ≤ n ≤ 3
1 ≤ k ≤ 5

 

输出

输出一个 N K×N K 的矩阵表示答案,不允许有多余的空行或空格。

样例输入

2 3
.*
..

样例输出

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

【分析】数据很小,暴力模拟。注意一下细节要。定义一个二维字符数组做中转

【代码】

#include<bits/stdc++.h>
using namespace std;

const int maxn=300;
char mp[maxn][maxn];//最终图 
char s[maxn][maxn];//中间图 
char s0[5][5];//原始模板 

int n,k;

int main()
{
	scanf("%d%d",&n,&k);
	for(int i=0;i<n;i++)scanf("%s",s0[i]);
	int side=1;
	mp[0][0]='.';
	while(k--)
	{
		for(int i=0;i<side;i++)
			for(int j=0;j<side;j++)
			{
				if(mp[i][j]=='.')
					for(int p=0;p<n;p++)
						for(int q=0;q<n;q++)
							s[i*n+p][j*n+q]=s0[p][q];
				else
				for(int p=0;p<n;p++)
						for(int q=0;q<n;q++)
							s[i*n+p][j*n+q]='*';
			}
		side*=n;
		for(int i=0;i<side;i++)
			for(int j=0;j<side;j++)
				mp[i][j]=s[i][j];
	}
	for(int i=0;i<side;i++)printf("%s\n",mp[i]);
	return 0;
}

E 解密(水+有点巧妙的解法)

时间限制: 1  内存限制: 128 MB

提交: 109  解决: 59  201501010119

提交状态讨论版

题目描述

湖南中医药大学有含浦、东塘 2 个校区,学校办学历史悠久,前身为 1934 年的湖南国医专科学校,1953
年创办湖南中医进修学校,1960 年创建普通高等本科院校——湖南中医学院,1979 年成为全国首批取得
中医类研究生学历教育资格的院校,1990 年原湖南科技大学成建制并入湖南中医学院,2002 年与湖南省
中医药研究院合并,2006 年经教育部批准更名为湖南中医药大学,2012 年进入湖南省一本招生序列。
目前,学校与湖南省中医药研究院实行校院合一的管理体制。学校学科门类齐全、中医药特色鲜明。学校
设有 18 个学院、24 个本科专业,涵盖医、理、工、管、文等 5 大学科门类。中医诊断学在本学科研究领
域居国内领先水平。
小 F 居住在含浦校区,他想和东塘校区的同学小 L 聊天,为了保证沟通安全,他发明了一种加密方式,这
种加密方式是这样的:对于一个 01 串,小 F 会将其从左到右每 8 位分成一组,最后一组可能不足 8 位,
对每组进行逆序操作,即如果原来是 bLbL+1bL+2 · · · bR−1bR, 逆序之后变成 bRbR−1bR−2 · · · bL−1bL。现在
小 F 已经加密好了一个串,并且将其发给了小 L,你能帮助小 L 得到这串密文对应的原始信息吗?

输入

单组数据。
一行一个 01 串,代表加密后的字符串,串长度大于 0, 小于等于 100。

输出

一行字符串,代表加密后的字符串所对应的原始信。

样例输入

100010110011101

样例输出

110100011011100

【题意】字符串8个一组逆序输出。不足8个的也要逆序

【分析】水题啦,不过看了标程之后发现代码可以很简洁思维可以很巧妙!

【代码】

#include<bits/stdc++.h>
using namespace std;
 
char s[105];
 
int main()
{
    scanf("%s",s);
    int len=strlen(s);
    for(int i=0;i<len;i+=8)
    {
        int l=i,r=min(len-1,i+7);
        while(l<r)
        {
            swap(s[l],s[r]);
            l++;r--;
        }
    }
    puts(s);
}

F: 巍巍岳麓(类似最小生成树)

时间限制: 1  内存限制: 128 MB

提交: 90  解决: 25  201501010119

题目描述

岳麓山风景区位于湖南省长沙市岳麓区,占地面积 35.20 平方公里,是南岳衡山 72 峰的最后一峰,位于
橘子洲旅游景区内,为城市山岳型风景名胜区,是中国四大赏枫胜地之一。
岳麓山位于首批国家历史文化名城长沙市湘江西岸,依江面市,现有岳麓山、橘子洲、岳麓书院、新民学
会四个核心景区,为世界罕见的集“山、水、洲、城”于一体的国家 AAAAA 级旅游景区、国家重点风
景名胜区、湖湘文化传播基地和爱国主义教育的示范基地。
岳麓山因南朝宋时《南岳记》中“南岳周围八百里,回燕为首,岳麓为足”而得名,融中国古文化精华的
儒、佛、道为一体,包容了历史上思想巨子、高僧名道、骚人墨客共同开拓的岳麓山文化内涵。景区内有
岳麓书院、爱晚亭、麓山寺、云麓宫、新民学会旧址、黄兴墓、蔡锷墓、第九战区司令部战时指挥部旧址
等景点。
为了改善岳麓山周边的旅游环境,市长决定对道路进行改造,城市中有 n 个路口,有些交叉路口之间有
道路直接相连;两个交叉路口之间最多有一条道路相连接。这些道路是双向的,且能把所有的交叉路口直
接或间接连接起来。每条道路都有一个分值,分值越小表示这个道路越繁忙,越需要改造。但是市政府的
资金有限,市长希望进行改造的道路越少越好,于是提出了下面的要求,需要同时满足:
1、改造的那些道路能把所有的交叉路口直接或间接地连通起来;
2、改造的道路尽量少且改造的那些道路中分值最大的道路的分值尽量小;
3、紧邻岳麓山的麓山南路必须改造。
请你做出规划设计,选择哪些道路应当改造。

输入

单组数据。
输入第一行有两个正整数 n 和 m,分别表示城市有 n 个交叉路口,m 条道路 (n <= 3000,m<=4000)。
接下来 m 行是对每条道路的描述,u,v,c 表示交叉路口 u 和 v 之间有道路相连,分值为 c(分值不会超
过 int)。最后一行两个正整数 s 和 t,表示麓山南路在交叉路口 s 和 t 相连的路上。

输出

输出两个整数 tot,max,表示你选出了几条道路,分值最大的那条的道路的分值是多少。

样例输入

4 5
1 2 3
1 4 5
2 4 7
2 3 6
3 4 8
1 4

样例输出

3 6

【分析】因为有一条路是一定要加的,所以并查集的时候把这条路加进去再遍历边跑生成树再求最小值即可。

得到最大边的最小值。
选的路的数量必然是n-1(最小生成树);

#include<bits/stdc++.h>
using namespace std;

const int inf=0x3f3f3f3f;
const int maxn=4e5+10;
typedef long long ll;

struct node{
    int l,r,w;
}a[maxn];
int pre[maxn];
int n,m,s,t,ans;

bool cmp(node a, node b){ return a.w<b.w; }
int findd(int x){return x==pre[x]?x:findd(pre[x]);}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].w);
    sort(a+1,a+1+m,cmp);
    int index,maxx;
    scanf("%d%d",&s,&t);
    for(int i=1;i<=m;i++)
        if((a[i].l==s&&a[i].r==t) || (a[i].l==t&&a[i].r==s))
		{
            index=i;
            break;
        }
    ans=inf;
    for(int i=1;i<=m;i++)
	{
        for(int j=1;j<=n;j++)pre[j]=j;
        pre[s]=t;//必须连通的路,先加进去 
		maxx=a[index].w; 
        int k=1;
        for(int j=i;j<=m;j++)
		{
            int xx=findd(a[j].l),yy=findd(a[j].r);
            if(xx!=yy)
			{
                pre[yy]=xx;
                k++;
                maxx=max(maxx,a[j].w);
                if(k==n-1)break;
            }
        }
        if(k==n-1)   //能够形成生成树
            ans=min(ans,maxx);
    }
    printf("%d %d\n",n-1,ans);
    return 0;
}

H: 百舸争流(贪心)

时间限制: 1  内存限制: 128 MB

提交: 80  解决: 13  201501010119

提交状态讨论版

题目链接:http://acm.hnucm.edu.cn/JudgeOnline/problem.php?id=1372

题目描述

橘子洲风景区位于湖南省长沙市市区对面的湘江江心,是湘江中最大的名洲,由南至北,横贯江心,西望
岳麓山,东临长沙城,四面环水,绵延数十里,狭处横约 40 米,宽处横约 140 米,形状是一个长岛,是
国家重点风景名胜区。
一天,N 名选手参加了一年一度的橘洲竞渡大赛,现在只剩下最后一场决赛了!
赛制为积分制,N 名选手的积分分别为 A1 到 AN。决赛的积分规则如下:第一名得 B1 分,第二名得 B2
分,……,第 m 名得 Bm 分,第 m+1 名至第 n 名不得分。最后第 i 名选手的总得分为 Ai 加上他在决
赛中的得分。
我们按总分为第一关键字、名字的字典序为第二关键字对选手进行排序。现告诉你一名选手的名字,希望
你告诉他,他最终的排名最前可能是多少,最后可能是多少。

输入

单组数据。
第一行为一个数 n,表示有 n 名选手 (1 ≤ n ≤ 105)。

接下来有 n 行,每行由一个字符串 S 和一个非负整数 Ai 表示,代表该人的名字和决赛之前的总分。

(名字仅由英文字母和数字表示,长度不超过 20,没有相同名字的两个人,0 ≤ Ai ≤ 106)。

接下来一个数 m(0 ≤ m ≤ n)。
接下来一行 m 个数字依次表示 B1, B2, B3, · · · , Bm (0 ≤ Bi ≤ 106)。
最后一个字符串表示询问的选手的名字。

输出

输出两个数,第一个表示最终排名最前可能多少,第二个表示最后可能多少。

样例输入

3
CH1 10
CH2 20
CH3 40
2
20 10
CH1

样例输出

2 3

【题意】给出n个人的分数以及最后一场的前m名可以加分的分数,询问其中一位选手的最终排名的最好名次和最差名次。

【分析】先把n个人的分数和最后一场可加分的分数进行排序。找到要查询的那个人,记录下其分数以及当前排名。

最好名次:把可加的最好分数加给这个人那么这个人分数是grade1,初始排名pm1设置为n,然后往后枚举的时候,如果加上b[i](排序之后是升序的,now从n-2开始)的分数仍然小于grade1或...那么排名要上升的。如果循环完所有的b[i]都比grade1大即这个人的排名不能上升,直到now<0退出循环。

int grade1=grade+b[n-1];
int now=n-2;
for(int i=n-1;i>=0&&now>=0;i--)
{
	if(i!=pm)
	{
		while(now>=0)
		{
			if(a[i].score+b[now]<grade1 || (a[i].score+b[now]==grade1&&a[i].name>a[pm].name))break;
			now--;
		}
		now--;
		if(now<0)break;
		pm1--;
	}
}

最差名次同理。

【代码】

#include<bits/stdc++.h>
using namespace std;

const int maxn=1e5+10;
struct node{
	string name;
	int score;
}a[maxn];
int b[maxn]={0};

bool cmp(node x,node y)
{
	return x.score!=y.score?x.score>y.score:x.name<y.name;
}

int main()
{
	int n;scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		cin>>a[i].name;
		scanf("%d",&a[i].score);
	}
	int m;scanf("%d",&m);
	memset(b,0,sizeof(b));
	for(int i=0;i<m;i++)scanf("%d",&b[i]);
	string s;cin>>s;
	int grade,pm=0;
	sort(a,a+n,cmp);sort(b,b+n);
	for(int i=0;i<n;i++)
	{
		if(a[i].name==s)
		{
			grade=a[i].score;
			pm=i;
			break;
		}
	}
	int pm1=n,pm2=1;
	//good
	int grade1=grade+b[n-1];
	int now=n-2;
	for(int i=n-1;i>=0&&now>=0;i--)
	{
		if(i!=pm)
		{
			while(now>=0)
			{
				if(a[i].score+b[now]<grade1 || (a[i].score+b[now]==grade1&&a[i].name>a[pm].name))break;
				now--;
			}
			now--;
			if(now<0)break;
			pm1--;
		}
	}
	//bad
	int grade2=grade+b[0];
	now=1;
	for(int i=0;i<n&&now<n;i++)
	{
		if(i!=pm)
		{
			while(now<n)
			{
				if(a[i].score+b[now]>grade2 || (a[i].score+b[now]==grade2&&a[i].name<a[pm].name))break;
				now++;
			}
			if(now>=n)break;
			pm2++;
		}
	}
	printf("%d %d\n",pm1,pm2);
	return 0;
}

 

 

 

 

展开阅读全文

没有更多推荐了,返回首页