Problem A: 奇怪的排序
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 22 Solved: 13
[Submit][Status][Web Board]
Description
最近,Dr. Kong 新设计一个机器人Bill。这台机器人很聪明,会做许多事情。惟独对自然数的理解与人类不一样,它是从右往左读数。比如,它看到123时,会理解成321。让它比较23与15哪一个大,它说15大。原因是它的大脑会以为是32与51在进行比较。再比如让它比较29与30,它说29大。
给定Bill两个自然数A和B,让它将 [A,B] 区间中的所有数按从小到大排序出来。你会认为它如何排序?
Input
第一行: N 表示有多少组测试数据。
接下来有N行,每一行有两个正整数A B 表示待排序元素的区间范围。
2<=N<=5 1<=A<=B<=200000 B-A<=50。
Output
对于每一行测试数据,输出一行,为所有排好序的元素,元素之间有一个空格。
Sample Input
2
8 15
22 39
Sample Output
10 8 9 11 12 13 14 15
30 31 22 32 23 33 24 34 25 35 26 36 27 37 28 38 29 39
处理一下排序就好。。
#include<bits/stdc++.h> using namespace std; int T; int s,e; class A { public: int now,ori; }; bool operator < (const A &a,const A &b) { return a.now<b.now; } A a[1000000],b[1000000]; int n=0; A calc(int t) { if(a[t].now)return a[t]; int tt=a[t].ori; while(tt) { a[t].now*=10; a[t].now+=(tt%10); tt/=10; } return a[t]; } int main() { freopen("in.txt","r",stdin); while(~scanf("%d",&T)) { while(T--) { n=0; scanf("%d %d",&s,&e); for(int i=s;i<=e;i++) { a[i].ori=i; b[n++]=calc(i); } sort(b,b+n); for(int i=0;i!=n;i++) { if(i)printf(" "); printf("%d",b[i].ori); } printf("\n"); } } return 0; }
Problem B: 最强DE战斗力
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 30 Solved: 8
[Submit][Status][Web Board]
Description
春秋战国时期,赵国地大物博,资源非常丰富,人民安居乐业。但许多国家对它虎视眈眈,准备联合起来对赵国发起一场战争。
显然,面对多个国家的部队去作战,赵国的兵力明显处于劣势。战斗力是决定战争成败的关键因素,一般来说,一支部队的战斗力与部队的兵力成正比。但当把一支部队分成若干个作战队伍时,这个部队的战斗力就会大大的增强。
一支部队的战斗力是可以通过以下两个规则计算出来的:
1.若一支作战队伍的兵力为N,则这支作战队伍的战斗力为N;
2.若将一支部队分为若干个作战队伍,则这支部队的总战斗力为这些作战队伍战斗力的乘积。
比如:一支部队的兵力为5时的战斗力分析如下:
情况
作战安排
总的战斗力
1
1,1,1,1,1(共分为5个作战队伍)
11111=1
2
1,1,1,2 (共分为4个作战队伍)
111*2=2
3
1,2,2 (共分为3个作战队伍)
122=4
4
1,1,3 (共分为3个作战队伍)
113=3
5
2,3 (共分为2个作战队伍)
2*3=6
6
1,4 (共分为2个作战队伍)
1*4=4
7
5 (共分为1个作战队伍)
5=5
显然,将部队分为2个作战队伍(一个为2,另一个为3),总的战斗力达到最大!
Input
第一行: N 表示有N组测试数据。 (2<=N<=5)
接下来有N行,每行有一个整数Ti 代表赵国部队的兵力。 (1 <= Ti <= 1000)i=1,…N
Output
对于每一行测试数据,输出占一行,仅一个整数S, 表示作战安排的最大战斗力。
Sample Input
2
5
4
Sample Output
6
4
本来以为是dp,打个表就好了,然而打完一看,越界了。
1000个人,假如全2人两人分,是2^500,好吧不是DP而是个大数问题,那么问题来了。
是不是有最优的分解方式呢?
具体分析见:https://blog.csdn.net/u012349696/article/details/45098941
感谢大佬。
之后就模拟一下大数相乘就好。
#include<bits/stdc++.h> using namespace std; const int maxn=10000; int T,n; int a[maxn]; int cnt=0; void f(int t) { for(int i=0;i!=cnt;i++) { a[i]*=t; } int cnt2=0; while(cnt2<=cnt) { if(a[cnt2]>9) { int nextt=cnt2+1; a[nextt]+=(a[cnt2]/10); a[cnt2]%=10; if(nextt>=cnt)cnt++; } cnt2++; } } int main() { freopen("in.txt","r",stdin); while(~scanf("%d",&T)) { while(T--) { memset(a,0,sizeof(a)); a[0]=1; cnt=1; scanf("%d",&n); if(n<=4)printf("%d\n",n); else { int re=n%3; int de=n/3; if(re==1) { de--; re=4; } if(re)f(re); while(de--)f(3); for(int i=cnt-1;i>=0;i--) { printf("%d",a[i]); } printf("\n"); } } } return 0; }
Problem C: 试 制 品
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 12 Solved: 6
[Submit][Status][Web Board]
Description
ZZ大学的Dr.Kong最近发现实验室的很多试制品都已经用完。由于项目经费有限,为了节省,Dr.Kong决定利用实验室现有的试制品来生成所缺的试制品。为此,Dr.Kong连续几天通宵达旦整理出一份研究资料并让研究生Bill去实验并统计能产生多少种所缺的试制品。
Bill从头到尾翻完所有的资料,发现资料上写满了一大堆的化学方程式,上面除了大小写英文字母、数字、加号、等号外,再也没有其他的符号了。其中,每个方程式都是A1+A2+……+Ap=B1+B2+……+Bq的形式, 表示试制品A1,A2,……和Ap反应,生成了试制品B1,B2,……,Bq。其中Ai和Bj都是一种单质或化合物的化学式(长度不超过10个字符),1≤p,q ≤ 20 。每个方程式的总长不超过100个字符。有些试制品的化学式可能在现代社会的化学元素周期表里找不到,这是由于化学反应过程中可能又有物理反应导致的结果。
Bill头疼了,从哪个实验开始呢?你能帮助他吗?
Input
第一行: N 表示Dr.Kong写的化学方程式个数 (1≤ N ≤ 400)
接下来有N行, 每一行是一个方程式。
再接下来的一行:M 表示已有多少种试制品。 (1≤ M ≤500)
接下来有M行,每一行是已有的一种试制品的化学式。
Output
第一行包含一个数T,表示可以产生多少种所缺的试制品。
在接下来的T行中,按ASCII码升序输出产生的试制品的化学式。
Sample Input
4
H2O+Na=NaOH+H2
Cl2+H2=HCl
Fe+O2=Fe3O4
NaOH+HCl=H2O+NaCl
3
H2O
Na
Cl2
Sample Output
4
H2
HCl
NaCl
NaOH
这道题给我的启示就是,该暴力写就暴力写,不要总想着映射啊,优化啊,节省空间啊。
你先写出来个暴力的好不好。
一开始就想着优化,导致自己在编写的时候自己给自己找麻烦。
Orz
#include<bits/stdc++.h> using namespace std; const int maxn=500; int n,m; map<string,int> map1; set<string> set1; int cnt=0; bool vis[maxn]; class F { public: set<string> s1,s2; }; F f[maxn]; string str; set<string> ans; void init() { map1.clear(); for(int i=0;i!=maxn;i++) { f[i].s1.clear(); f[i].s2.clear(); } set1.clear(); memset(vis,0,sizeof(vis)); ans.clear(); } void out() { set<string>::iterator it; for(it=set1.begin();it!=set1.end();it++) { cout<<*it<<endl; } cout<<endl; } int main() { freopen("in.txt","r",stdin); while(~scanf("%d",&n)) { init(); cnt=1; cin.get(); for(int i=0;i!=n;i++) { getline(cin,str); string t=""; int j=0; for(j=0;j!=str.size();j++) { if(str[j]=='=')break; if(str[j]=='+') { f[i].s1.insert(t); t=""; } else { t+=str[j]; } } f[i].s1.insert(t); j++; t=""; for(;j!=str.size();j++) { if(str[j]=='+') { f[i].s2.insert(t); t=""; } else { t+=str[j]; } } f[i].s2.insert(t); // set<string>::iterator it; // for(it=f[i].s1.begin();it!=f[i].s1.end();it++) // { // cout<<*it<<" "; // } // cout<<" ----> "; // for(it=f[i].s2.begin();it!=f[i].s2.end();it++) // { // cout<<*it<<" "; // } // cout<<endl; } scanf("%d",&m); cin.get(); for(int i=0;i!=m;i++) { getline(cin,str); set1.insert(str); } bool flag=1; while(flag) { flag=0; for(int i=0;i!=n;i++) { if(vis[i])continue; bool flag1=1; set<string>::iterator it; for(it=f[i].s1.begin();it!=f[i].s1.end();it++) { if(set1.find(*it)==set1.end()) { flag1=0; break; } } if(flag1==0)continue; flag=1; for(it=f[i].s2.begin();it!=f[i].s2.end();it++) { if(set1.find(*it)==set1.end()) { ans.insert(*it); set1.insert(*it); } } vis[i]=1; } } cout<<ans.size()<<endl; set<string>::iterator it; for(it=ans.begin();it!=ans.end();it++) { cout<<*it<<endl; } } return 0; }
Problem D: 遥 控 器
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 6 Solved: 2
[Submit][Status][Web Board]
Description
Dr.Kong 有一台高级电视机,这台电视机可以接受100个频道(从0到99编号)。电视的配套遥控器有13个按钮:
1 2 3 ↑
4 5 6 ↓
7 8 9
— 0
当按"↑"键时,当前频道编号会增加1(如果当前为99频道,则会切换到0频道)。如果按"↓"键,当前频道编号会减小1(如果当前为0频道,则会切换到99频道)。当要切换到09频道时,可以直接在遥控器上按相应的键。当要切换到1099频道时,可以先按"—"键,然后按2个与频道编号相对应的数字键(即先按与频道编号的十位数字相对应的键,然后按与个位数字相对应的键)。
由于遥控器长时间的使用和某些未知原因,遥控器上的某些键已经坏了,不能再起作用了。现在你的任务是,能否告诉Dr.Kong,如何用最少的按键次数来将频道从编号X切换到编号Y。
Input
第一行: N 表示有N组测试数据。 (1<=N<=5)
对每组测试数据有5行,前4行包含遥控器上每个按键的信息。0表示对应的键坏了,1表示对应的键可以使用。第5行包含2个整数,分别是X 和 Y (0 <= X <= 99; 0 <= Y <= 99)。
Output
对每组测试数据输出一行,即将频道从编号X切换到编号Y所需要的最小按键次数。如果不可能将频道从编号X 切换到编号Y,则输出-1.
Sample Input
2
0 0 1 1
1 1 1 1
1 1 1
1 1
23 52
1 1 1 0
1 1 1 0
1 0 1
0 1
23 52
Sample Output
4
-1
最小的步数嘛,然后考虑到电视台的总数又不多,所以广搜一波就好。
但是注意采用那个 - 功能键,来进行双数台的跳转的时候需要用三步,可能比单步功能键慢。
我们在使用单步键时,要对这个进行一下优化距离就好
#include<bits/stdc++.h> using namespace std; int T; bool on[13]; int x,y; int dis[100]; void bfs() { memset(dis,0,sizeof(dis)); dis[x]=1; queue<int> q; q.push(x); while(q.size()) { int p=q.front(); q.pop(); //°´Ò»¸öÊý×Ö¼ü½øÐÐÌø×ªµÄ·½·¨ //µ¥²½¹¦Äܼü for(int i=0;i!=10;i++) { if(!on[i])continue; if(!dis[i]) { dis[i]=dis[p]+1; q.push(i); } } //µ¥²½¹¦Äܼü if(on[10]) { int nextx=p+1; if(nextx>99)nextx-=100; //Èç¹ûûÓзÃÎʹý£¬»òÕßʹÓõ¥²½¼ü±È֮ǰµÄÈý²½¼ü¿ì£¬ÄÇôÎÒÃÇÖØÐ¼ÆËã if(!dis[nextx]||dis[p]+1<dis[nextx]) { dis[nextx]=dis[p]+1; q.push(nextx); } } //µ¥²½¹¦Äܼü if(on[11]) { int nextx=p-1; if(nextx<0)nextx+=100; //Èç¹ûûÓзÃÎʹý£¬»òÕßʹÓõ¥²½¼ü±È֮ǰµÄÈý²½¼ü¿ì£¬ÄÇôÎÒÃÇÖØÐ¼ÆËã if(!dis[nextx]||dis[p]+1<dis[nextx]) { dis[nextx]=dis[p]+1; q.push(nextx); } } //Èý²½¹¦Äܼü if(on[12]) { //Èç¹ûÄÜʹÓÃÌø×ª¼ü£¬ÄÇôÎÒÃÇ¿ÉÒÔÌø×ªµ½Á½Î»ÊýµĄ̈£¬ //ö¾ÙËùÓпÉÄܵĄ̈£¬±Ï¾¹ÎÒÃÇÊÇbfs //ö¾ÙʮλÊýµÄÊý×Ö for(int i=0;i!=10;i++) { if(!on[i])continue; //ö¾Ù¸öλÊý for(int j=0;j!=10;j++) { if(!on[j])continue; int nextx=i*10+j; if(!dis[nextx]) { //ÓпÉÄÜʹÓõ¥²½°´¼üÒª°´Á½Ï²ÅÄܵ½£¬µ«°´Èý²½¼üһϵ½ÁË£¬ //ÎÒÃÇÒªÔÚµ¥²½¼üÄÇÀï¶ÔÕâÖÖ²»´ÏÃ÷µÄÈý²½¼ü½øÐÐÓÅ»¯ dis[nextx]=dis[p]+3; q.push(nextx); } } } } } } int main() { freopen("in.txt","r",stdin); while(~scanf("%d",&T)) { while(T--) { int t; for(int i=1;i<=3;i++) { scanf("%d",&t); on[i]=t; } scanf("%d",&t);on[10]=t; for(int i=4;i<=6;i++) { scanf("%d",&t); on[i]=t; } scanf("%d",&t);on[11]=t; for(int i=7;i<=9;i++) { scanf("%d",&t); on[i]=t; } scanf("%d",&t);on[12]=t; scanf("%d",&t);on[0]=t; scanf("%d %d",&x,&y); // for(int i=0;i!=13;i++) // { // cout<<on[i]; // } // cout<<endl; // cout<<x<<y<<endl; bfs(); if(dis[y]==0) { printf("-1\n"); } else { printf("%d\n",dis[y]-1); } } } return 0; }
Problem E: 奇妙的图案
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 0 Solved: 0
[Submit][Status][Web Board]
Description
最近,Dr. Kong对几何图形发生了浓厚的兴趣。他发现在一个凸多边形里随意加上几个等半径的圆,再将圆涂成不同的颜色,就能构造出一幅美妙的图案。进而,Dr. Kong大发灵感,在此图案的基础上,又加入了几条连接凸多边形的两个不相邻顶点的直线,图形更加奇妙。
这时,Dr. Kong遇到了一个问题,他不想让加入的直线相互交叉,也不想让加入的直线穿过凸多边形里的任何一个圆,甚至不能与任何圆相切。
已经知道凸多边形的N个顶点的坐标,也知道了其中M个圆的圆心坐标和半径R。你能帮助Dr. Kong计算出可加上的满足所有条件的最多直线数吗?
Input
第1行: N M R 三个正整数
接下来有N行, 每一行为凸多边形一个坐标TXi TYi (i=1,…,N)
再接下来有M行,每一行为一个圆的圆心坐标PXj PYj (j=1,…,M)
Output
输出有一个整数, 表示可加上的最多直线数。
5≤ N ≤150 0≤ M ≤100 1≤ R ≤100,000 0≤ 所有坐标X,Y≤100,000
Sample Input
5 3 1
6 10
10 7
9 1
2 0
0 3
2 2
5 6
8 3
Sample Output
1
网上没搜到题解,个人感觉要涉及到分治的思想。
就是看看用一条边,把整个图形分成两半左边的最大值加右边的最大值,由于一个大块可能需要被求解很多次,所以我们采用记忆的方式来加速。但是。。。。,并不是太会写,也没有相关代码可以参考学习,那么我就暂时先不去磕这题了。
哦,还有样例的一个图,可以先放这里:
那个应该是话的不标准的原因,哈哈,我居然可以同时画两条不相交的线。。。
Problem F: Metric Matrice
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 8 Solved: 5
[Submit][Status][Web Board]
Description
nt j, determine if the distance matrix is “a metric” or not.
A distance matrix a[i][j] is a metric if and only if
1. a[i][i] = 0 2. a[i][j]> 0 if i != j 3. a[i][j] = a[j][i] 4. a[i][j] + a[j][k] >= a[i][k] i ¹ j ¹ k
Input
The first line of input gives a single integer, 1 ≤ N ≤ 5, the number of test cases. Then follow, for each test case,
-
Line 1: One integer, N, the rows and number of columns, 2 <= N <= 30
-
Line 2…N+1: N lines, each with N space-separated integers
(-32000 <=each integer <= 32000).
Output
Output for each test case , a single line with a single digit, which is the lowest digit of the possible facts on this list:
* 0: The matrix is a metric * 1: The matrix is not a metric, it violates rule 1 above * 2: The matrix is not a metric, it violates rule 2 above * 3: The matrix is not a metric, it violates rule 3 above * 4: The matrix is not a metric, it violates rule 4 above
Sample Input
2
4
0 1 2 3
1 0 1 2
2 1 0 1
3 2 1 0
2
0 3
2 0
Sample Output
0
3
嗯,是个模拟题,没啥好说的,我居然还wa了一发。。。
#include<bits/stdc++.h> using namespace std; const int maxn=35; int T,n; int map1[maxn][maxn]; bool check1() { for(int i=0;i!=n;i++) { if(map1[i][i])return 0; } return 1; } bool check2() { for(int i=0;i!=n;i++) { for(int j=0;j!=n;j++) { if(i==j)continue; if(map1[i][j]<=0)return 0; } } return 1; } bool check3() { for(int i=0;i!=n;i++) { for(int j=0;j!=i;j++) { if(map1[i][j]!=map1[j][i])return 0; } } return 1; } bool check4() { for(int i=0;i!=n;i++) { for(int j=0;j!=n;j++) { for(int k=0;k!=n;k++) { if(i==j||j==k||i==k)continue; if(map1[i][j]+map1[j][k]<map1[i][k])return 0; } } } return 1; } int main() { freopen("in.txt","r",stdin); while(~scanf("%d",&T)) { while(T--) { scanf("%d",&n); for(int i=0;i!=n;i++) { for(int j=0;j!=n;j++) { scanf("%d",&map1[i][j]); } } if(!check1()) { printf("1\n"); } else if(!check2()) { printf("2\n"); } else if(!check3()) { printf("3\n"); } else if(!check4()) { printf("4\n"); } else { printf("0\n"); } } } return 0; }