A:有趣的跳跃
总时间限制: 1000ms 内存限制: 65536kB
描述
一个长度为n(n>0)的序列中存在“有趣的跳跃”当前仅当相邻元素的差的绝对值经过排序后正好是从1到(n-1)。例如,1 4 2 3存在“有趣的跳跃”,因为差的绝对值分别为3,2,1。当然,任何只包含单个元素的序列一定存在“有趣的跳跃”。你需要写一个程序判定给定序列是否存在“有趣的跳跃”。
输入
一行,第一个数是n(0 < n < 3000),为序列长度,接下来有n个整数,依次为序列中各元素,各元素的绝对值均不超过1,000,000,000。
输出
一行,若该序列存在“有趣的跳跃”,输出"Jolly",否则输出"Not jolly"。
样例输入
4 1 4 2 3
样例输出
Jolly
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
const int INF=3000;
int n=0;
int in[INF];
int cha[INF];
int main(){
memset(cha,0,sizeof(cha));
scanf("%d",&n);
scanf("%d",&in[0]);
for(int i=1;i<n;i++){
scanf("%d",&in[i]);
cha[abs(in[i]-in[i-1])]=1;
}
for(int i=1;i<=n-1;i++){
if(cha[i]==0){
printf("Not Jolly");
return 0;
}
}
printf("Jolly");
return 0;
}
B:玛雅历
总时间限制: 1000ms 内存限制: 65536kB
描述
上周末,M.A. Ya教授对古老的玛雅有了一个重大发现。从一个古老的节绳(玛雅人用于记事的工具)中,教授发现玛雅人使用了一个一年有365天的叫做Haab的历法。这个Haab历法拥有19个月,在开始的18个月,一个月有20天,月份的名字分别是pop, no, zip, zotz, tzec, xul, yoxkin, mol, chen, yax, zac, ceh, mac, kankin, muan, pax, koyab, cumhu。这些月份中的日期用0到19表示。Haab历的最后一个月叫做uayet,它只有5天,用0到4表示。玛雅人认为这个日期最少的月份是不吉利的,在这个月法庭不开庭,人们不从事交易,甚至没有人打扫屋中的地板。
因为宗教的原因,玛雅人还使用了另一个历法,在这个历法中年被称为Tzolkin(holly年),一年被分成13个不同的时期,每个时期有20天,每一天用一个数字和一个单词相组合的形式来表示。使用的数字是1~13,使用的单词共有20个,它们分别是:imix, ik, akbal, kan, chicchan, cimi, manik, lamat, muluk, ok, chuen, eb, ben, ix, mem, cib, caban, eznab, canac, ahau。注意:年中的每一天都有着明确唯一的描述,比如,在一年的开始,日期如下描述: 1 imix, 2 ik, 3 akbal, 4 kan, 5 chicchan, 6 cimi, 7 manik, 8 lamat, 9 muluk, 10 ok, 11 chuen, 12 eb, 13 ben, 1 ix, 2 mem, 3 cib, 4 caban, 5 eznab, 6 canac, 7 ahau, ,8 imix, 9 ik, 10 akbal ……也就是说数字和单词各自独立循环使用。
Haab历和Tzolkin历中的年都用数字0,1,……表示,数字0表示世界的开始。所以第一天被表示成:
Haab: 0. pop 0
Tzolkin: 1 imix 0
请帮助M.A. Ya教授写一个程序可以把Haab历转化成Tzolkin历。
输入
Haab历中的数据由如下的方式表示:
日期. 月份 年数
输入中的第一行表示要转化的Haab历日期的数据量。下面的每一行表示一个日期,年数小于5000。
输出
Tzolkin历中的数据由如下的方式表示:
天数字 天名称 年数
第一行表示输出的日期数量。下面的每一行表示一个输入数据中对应的Tzolkin历中的日期。
样例输入
3
10. zac 0
0. pop 0
10. zac 1995
样例输出
3
3 chuen 0
1 imix 0
9 cimi 2801
来源
POJ 1008
#include <stdio.h>
#include <string>
#include <map>
using namespace std;
int n,td,tm,ty,totd,ad,am,ay,ads;
string tms;
map<string,int> hton;
map<int,string> ntot;
string ha[20]={"pop","no","zip",
"zotz","tzec","xul",
"yoxkin"," mol","chen",
"yax","zac","ceh",
"mac","kankin","muan",
"pax","koyab","cumhu",
"uayet"};
string ta[25]={"imix"," ik"," akbal",
" kan"," chicchan"," cimi",
" manik"," lamat"," muluk",
" ok"," chuen"," eb",
" ben"," ix"," mem",
" cib"," caban"," eznab",
" canac"," ahau"};
int main(){
for(int i=0;i<19;i++){
hton[ha[i]]=i;
}
for(int i=0;i<20;i++){
ntot[i]=ta[i];
}
tms.resize(3);
scanf("%d",&n);
printf("%d\n",n);
for(int i=0;i<n;i++){
scanf("%d. %s %d",&td,&tms[0],&ty);
tm=hton[tms];
totd=ty*365+tm*20+td;
ay=totd/(20*13);
ads=totd%(20*13);
am=ads%20;
ad=ads%13;
printf("%d %s %d\n",ad+1,ntot[am].c_str(),ay);
}
return 0;
}
C:走迷宫
总时间限制: 1000ms 内存限制: 65536kB
描述
一个迷宫由R行C列格子组成,有的格子里有障碍物,不能走;有的格子是空地,可以走。
给定一个迷宫,求从左上角走到右下角最少需要走多少步(数据保证一定能走到)。只能在水平方向或垂直方向走,不能斜着走。
输入
第一行是两个整数,R和C,代表迷宫的长和宽。( 1<= R,C <= 40)
接下来是R行,每行C个字符,代表整个迷宫。
空地格子用’.‘表示,有障碍物的格子用’#‘表示。
迷宫左上角和右下角都是’.’。
输出
输出从左上角走到右下角至少要经过多少步(即至少要经过多少个空地格子)。计算步数要包括起点和终点。
样例输入
5 5
…###
#…
#.#.#
#.#.#
#.#…
样例输出
9
#include <stdio.h>
#include <string>
#include <queue>
using namespace std;
const int INF=100;
struct Node{
int nr,nc;
int sp;
};
queue<Node> ge;
int mapp[INF][INF];
int r,c;
int dir[4][2]={1,0,
0,1,
-1,0,
0,-1};
int main(){
scanf("%d %d",&r,&c);
char tp;
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
scanf("%c",&tp);
mapp[i][j]= tp=='.'?1:0;//1空地0物品
}
}
Node temp,tnext;
temp.nc=temp.nr=temp.sp=0;
ge.push(temp);
while(!ge.empty()){
temp=ge.front();ge.pop();
for(int i=0;i<4;i++){
tnext=temp;
tnext.nr+=dir[i][0];
tnext.nc+=dir[i][1];
tnext.sp++;
printf("%d %d %d--\n",tnext.nr,tnext.nc,tnext.sp);
if(tnext.nr>=r||tnext.nc>=c||tnext.nr<0||tnext.nc<0)
continue;
if(tnext.nr==r-1&&tnext.nc==c-1){
printf("%d",tnext.sp+1);
return 0;
}
ge.push(tnext);
}
}
printf("No path\n");
return 0;
}
D:最大上升子序列和
总时间限制: 1000ms 内存限制: 65536kB
描述
一个数的序列bi,当b1 < b2 < … < bS的时候,我们称这个序列是上升的。对于给定的一个序列(a1, a2, …,aN),我们可以得到一些上升的子序列(ai1, ai2, …, aiK),这里1 <= i1 < i2 < … < iK <= N。比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。这些子序列中序列和最大为18,为子序列(1, 3, 5, 9)的和.
你的任务,就是对于给定的序列,求出最大上升子序列和。注意,最长的上升子序列的和不一定是最大的,比如序列(100, 1, 2, 3)的最大上升子序列和为100,而最长上升子序列为(1, 2, 3)
输入
输入的第一行是序列的长度N (1 <= N <= 1000)。第二行给出序列中的N个整数,这些整数的取值范围都在0到10000(可能重复)。
输出
最大上升子序列和
样例输入
7
1 7 3 5 9 4 8
样例输出
18
#include <stdio.h>
using namespace std;
const int INF=100;
int n,maxx=0;
int a[INF];
int dp[INF];
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
dp[0]=a[0];
for(int i=1;i<n;i++){
dp[i]=a[i];
for(int j=0;j<i;j++){
if(a[j]<=a[i]){
dp[i]=(a[i]+dp[j])>dp[i]?(a[i]+dp[j]):dp[i];
}
}
maxx=maxx>dp[i]?maxx:dp[i];
}
printf("%d",maxx);
return 0;
}
E:酸奶厂
总时间限制: 1000毫秒 内存限制: 65536kB
描述
奶牛购买了一家酸奶厂,该酸奶厂生产举世闻名的Yucky酸奶。在接下来的N(1 <= N <= 10,000)周内,牛奶和劳动力的价格将每周波动,从而使公司在一周内生产一单位酸奶的成本为C_i(1 <= C_i <= 5,000)美分一世。经过精心设计的Yucky工厂,每周可生产任意数量的酸奶。
Yucky Yogurt拥有一个仓库,可以按每周每单位酸奶S(1 <= S <= 100)美分的固定费用存储未使用的酸奶。幸运的是,酸奶不会变质。Yucky酸奶的仓库很大,因此可以容纳许多单位的酸奶。
Yucky希望找到一种方法来每周向其客户交付Y_i(0 <= Y_i <= 10,000)单位酸奶(Y_i是第i周的交付量)。帮助Yucky在整个N周的时间内最大程度地降低其成本。第i周生产的酸奶以及已经储存的任何酸奶都可以用来满足Yucky当周的需求。
输入
*第1行:两个以空格分隔的整数N和S。
*第2…N + 1行:第i + 1行包含两个以空格分隔的整数:C_i和Y_i。
输出
*第1行:第1行包含一个整数:满足酸奶时间表的最低总成本。请注意,对于32位整数,总数可能太大。
样例输入
4 5
88 200
89 400
97 300
91 500
样例输出
126900
#include <stdio.h>
using namespace std;
const int INF=10020;
int n,s;
int a[INF][2];
long long int tot=0;
int main(){
scanf("%d %d",&n,&s);
for(int i=0;i<n;i++){
scanf("%d %d",&a[i][0],&a[i][1]);
a[i][2]=0;
}
for(int i=0;i<n;i++){
tot+=a[i][0]*a[i][1];
if(i!=n-1){
a[i+1][0]=a[i+1][0]<(a[i][0]+s)?a[i+1][0]:(a[i][0]+s);
}
}
printf("%lld",tot);
return 0;
}
无线网络
描述
东南亚发生地震。亚洲合作医疗队(ACM)已与膝上计算机建立了无线网络,但由于意外的余震袭击,网络中的所有计算机都被破坏了。电脑被一一修复,网络逐渐恢复工作。由于硬件限制,每台计算机只能直接与不超过d米的计算机通信。但是,每台计算机都可以视为其他两台计算机之间通信的中介,也就是说,如果计算机A和计算机B可以直接通信,或者有计算机C可以同时与A和B通信,则计算机A和计算机B可以通信。 B.
在修复网络的过程中,工作人员可以随时执行两种操作,即修复一台计算机或测试两台计算机是否可以通信。您的工作是回答所有测试操作。
输入项
第一行包含两个整数N和d(1 <= N <= 1001,0 <= d <= 20000)。N是计算机的数量,从1到N,而D是两台计算机可以直接通信的最大距离。在接下来的N行中,每行包含两个整数xi,yi(0 <= xi,yi <= 10000),这是N个计算机的坐标。从第(N + 1)行到输入的末尾,有一些操作,这些操作是一个接一个地执行的。每行包含以下两种格式之一的操作:
1.“ O p”(1 <= p <= N),表示修复计算机p。
2.“ S p q”(1 <= p,q <= N),表示测试计算机p和q是否可以通信。
输入不会超过300000行。
输出量
对于每项测试操作,如果两台计算机可以通信,则打印“ SUCCESS”,否则,请打印“ FAIL”。
题目描述
#include <stdio.h>
#include <string.h>
#include <math.h>
using namespace std;
const int INF=1010;
const double epss=1e-3;
int n,s,tpp,tp1,tp2;
char tp;
int point[INF][2];
int vis[INF];
int in[INF];
int dist(int a,int b){
double r=pow((point[a][0]-point[b][0]),2);
double t=pow((point[a][1]-point[b][1]),2);
return sqrt(r+t);
}
int finrot(int a){
if(in[a]!=-1){
in[a]=finrot(in[a]);
return in[a];
}
return a;
}
int join(int a,int b){
in[finrot(a)]=finrot(b);
return 0;
}
int main(){
memset(vis,0,sizeof(vis));
memset(in,-1,sizeof(in));
scanf("%d %d",&n,&s);
for(int i=1;i<=n;i++){
scanf("%d %d",&point[i][0],&point[i][1]);
}
while(scanf("%c",&tp)!=EOF){//POJ要用cin scanf错了。
if(tp=='O'){
scanf("%d",&tpp);
vis[tpp]=1;
for(int i=1;i<=n;i++){
if(i==tpp||vis[i]==0){
continue;
}
if(dist(tpp,i)<=s+epss){
join(tpp,i);
}
}
}else if(tp=='S'){
scanf("%d %d",&tp1,&tp2);
tp1=finrot(tp1);
tp2=finrot(tp2);
if(tp1==tp2){
printf("SUCCESS\n");
}else{
printf("FAIL\n");
}
}
}
return 0;
}
Kruskal算法,由短到长排序,生成最小生成树,倒数的s-1条边用卫星通讯代替,由前向后第p-1-(s-1)条边的长度就是所求
题解
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int INF=505;
struct Edge{
int p1,p2;
double dis;
};
struct Poin{
int x,y;
};
Edge edge[INF*INF];
Poin poin[INF];
int in[INF];
double dist(int a,int b){
double t1=pow((poin[a].x-poin[b].x),2);
double t2=pow((poin[a].y-poin[b].y),2);
return sqrt(t1+t2);
}
int cmp(Edge a,Edge b){
return a.dis<b.dis;
}
int finrot(int i){
if(in[i]!=-1){
in[i]=finrot(in[i]);
return in[i];
}
return i;
}
int join(int a,int b){
a=finrot(a);
b=finrot(b);
if(a<b){
in[b]=a;
}
else{
in[a]=b;
}
return 0;
}
int main(){
int n,satt,pott;
scanf("%d",&n);
while(n--){
memset(in,-1,sizeof(in));
int nedge=0;
scanf("%d %d",&satt,&pott);
for(int i=0;i<pott;i++){
scanf("%d %d",&poin[i].x,&poin[i].y);
}
for(int i=0;i<pott;i++){
for(int j=i+1;j<pott;j++){
edge[nedge].p1=i;
edge[nedge].p2=j;
edge[nedge++].dis=dist(i,j);
}
}
sort(edge,edge+nedge,cmp);
for(int i=0,k=0;i<nedge;i++){
int rp1=finrot(edge[i].p1);
int rp2=finrot(edge[i].p2);
if(rp1!=rp2){
join(rp1,rp2);
k++;
if(k==pott-satt){
printf("%.2f\n",edge[i].dis);
break;
}
}
}
}
return 0;
}