题1
7-1 Lily
百合花(Lily)是一种美丽的花。她通常一年只开一次花,所以如果你看到百合花盛开,它会非常珍贵。然而,她对猫有剧毒,所以你必须注意让好奇的猫远离可爱的百合花。
你有n个网格的土壤土地排成一行,从1到n,其中一些是百合花。我们不想伤害百合,也不想伤害猫。你可以在网格上放一些猫粮,但对于任何有猫粮的网格i,在区域[i−1,i+1]不得含有百合花。你喜欢猫和百合,所以你想最大限度地增加有猫粮的格子。
设计满足上述要求的计划。
输入格式:
有一个整数n(1≤n≤1000)表示网格的数量。
第二行包含仅由“L”和“.”组成的字符串R,表示有和没有百合花的格子。
输出格式:
输出包含一行,字符串R′仅由“L”、“”组成和“C”,其中“C”表示在满足上述要求的同时分配给R中空网格的猫粮。
输入样例:
在这里给出一组输入。例如:
5
..L..
输出样例:
在这里给出相应的输出。例如:
C.L.C
思路:
将每个L及两边的位置标记为不可用,然后在可用位置上写入C
代码如下:
#include<iostream>
#include<string>
using namespace std;
int main()
{
int n;
cin >> n;
string s;
cin >> s;
int len = s.size();
int i;
bool a[1001];
for (i = 0; i <= 1000; i++)
{
a[i] = true;
}
if (s[0] == 'L')
{
a[0] = false;
a[1] = false;
}
for (i = 1; i < len-1; i++)
{
if (s[i] == 'L')
{
a[i - 1] = false;
a[i] = false;
a[i + 1] = false;
}
}
if (s[len-1] == 'L')
{
a[len-1] = false;
a[len-2] = false;
}
for (i = 0; i < len; i++)
{
if (a[i])
{
cout << "C";
}
else
{
cout << s[i];
}
}
return 0;
}
题2
7-2 a * b
给出两个不超过1000位的十六进制数a,b。
求a∗b的值
输入格式:
输入共两行,两个十六进制的数
输出格式:
输出一行,表示a∗b
输入样例:
在这里给出一组输入。例如:
1BF52
1D4B42
输出样例:
在这里给出相应的输出。例如:
332FCA5924
思路:
编写两个函数h2d和d2h将十进制和十六进制互相转换,然后用十进制高精度乘法的方法计算即可
代码如下:
#include<iostream>
#include<cstring>
using namespace std;
int h2d(char ch)
{
if(ch>='A')
{
return ch-'A'+10;
}
else
{
return ch-'0';
}
}
char d2h(int t)
{
if(t>=10)
{
return 'A'+t-10;
}
else
{
return '0'+t;
}
}
int main()
{
string s1,s2;
cin>>s1>>s2;
int t1[10000];
int t2[10000];
int ans[10000];
int tans[10000];
int l1=s1.length();
int l2=s2.length();
int max=0;
for(int i=0;i<l1;i++)
{
t1[i]=h2d(s1[l1-1-i]);
}
for(int i=0;i<l2;i++)
{
t2[i]=h2d(s2[l2-1-i]);
}
for(int i=0;i<l2;i++)
{
int jw=0;
for(int p=0;p<i;p++)
{
tans[p]=0;
}
for(int j=0;j<l1;j++)
{
int t=t1[j]*t2[i]+jw;
tans[j+i]=t % 16;
jw=t/16;
}
tans[l1+i]=jw;
int jw1=0;
for(int k=0;k<l1+l2;k++)
{
int b;
b=(tans[k]+ans[k]+jw1)%16;
jw1=(tans[k]+ans[k]+jw1)/16;
ans[k]=b;
}
ans[l1+l2]=jw1;
}
bool flag=false;
for(int i=l1+l2;i>=0;i--)
{
if(ans[i]==0 && !flag)
{
continue;
}
else
{
flag=true;
cout<<d2h(ans[i]);
}
}
return 0;
}
题3
7-3 山头狙击战
题目描述
小明为了掩护大部队,单枪匹马同敌人周旋,后来被敌人包围在某山头……等等,为什么怎么听怎么像狼牙山五壮士!不过不用着急,这次小明携带了足够的弹药,完全可以将涌上来的敌人一个一个干掉。小明是个神枪手,只要他的枪膛中有子弹,他就能将在他射程m(用从敌人位置到山头的直线距离算)以内的一个敌人瞬间射杀。但如果在射程内没有敌人,出于节约子弹考虑和面子问题,小明会等待敌人靠近然后射击。
正当小明为自己的强大而自我膨胀时,他忽然发现了一个致命的失误:他携带的枪是单发枪,每射出一发子弹都必须花k秒钟的时间装子弹。而凶残的敌人才不会花时间等你换子弹呢。他们始终在以1m/s的速度接近山头。而如果在一个敌人到达山头时小明无法将他击毙,那么我们可怜的小明就将牺牲在敌人的刺刀下。现在小明用心灵感应向你发出求助:要保住自己的性命并且歼灭所有敌人,小明最多只能用多少时间给枪装上一发子弹?
说明:假设一开始小明的枪中就有一发子弹,并且一旦确定一个装弹时间,小明始终会用这个时间完成子弹的装卸。希望你能帮助小明脱离险境。
输入格式
每组输入数据,第一行有两个整数n和m,(2≤n≤100,000; 1≤m≤10,000,000)n代表敌人个数,m代表小明的射程。
接下来有n行,每行一个整数mi,(1≤mi≤10,000,000),代表每个敌人一开始相对山头的距离(单位为米)。
输出格式
每组输出数据仅有一个整数,代表小明的换弹时间(单位为秒)。
样例输入
6 100
236
120
120
120
120
120
样例输出
25
思路:
由于直接得出答案较难,而判断已知答案是否正确较简单,且答案与过程有严格的单调性,所以我们采用二分答案。注意check()函数中 需优先考虑射程范围内的敌人再考虑外围敌人的位移,否则思路会不清晰。
代码如下:
#include <iostream>
#include<algorithm>
using namespace std;
int n, a[100001], m;
bool check(int x)
{
int t = 0;
for (int i = 1; i <= n; i++)
{
if (a[i] < t)
return false;
if (a[i] <= t + m)
t += x;
else
{
t += (a[i] - t - m);
t += x;
}
}
return true;
}
int main()
{
cin>>n>>m;
for (int i = 1; i <= n; i++)
cin>>a[i];
sort(a + 1, a + 1 + n);
int l = 0, r = 10000000;
while (l < r)
{
int mid = (l + r + 1) / 2;
if (check(mid)) l = mid;
else r = mid - 1;
}
cout<<l;
return 0;
}
题4:
7-4 Reversing Linked List
Given a constant K and a singly linked list L, you are supposed to reverse the links of every K elements on L. For example, given L being 1→2→3→4→5→6, if K=3, then you must output 3→2→1→6→5→4; if K=4, you must output 4→3→2→1→5→6.
Input Specification:
Each input file contains one test case. For each case, the first line contains the address of the first node, a positive N (≤105) which is the total number of nodes, and a positive K (≤N) which is the length of the sublist to be reversed. The address of a node is a 5-digit nonnegative integer, and NULL is represented by -1.
Then N lines follow, each describes a node in the format:
Address Data Next
where Address
is the position of the node, Data
is an integer, and Next
is the position of the next node.
Output Specification:
For each case, output the resulting ordered linked list. Each node occupies a line, and is printed in the same format as in the input.
Sample Input:
00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218
Sample Output:
00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1
思路:
使用递归函数依次翻转节点指向
代码如下:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node *List;
struct Node {
int Address;
int Data;
int Next;
List Nextptr;
};
#define MaxSize 100000
struct Node arr[MaxSize];
List ReadList(int firstAddr, int *length)
{
int i, list_size;
int addr, pos;
List L, p, temp;
L = (List)malloc(sizeof(struct Node)); L->Nextptr = NULL;
p = L;
memset(&arr, -1, sizeof(struct Node));
for ( i = 0; i < (*length); ++i ) {
scanf("%d", &addr);
arr[addr].Address = addr;
scanf("%d %d", &arr[addr].Data, &arr[addr].Next);
}
list_size = 0;
pos = firstAddr;
while (arr[pos].Address != -1) {
p->Nextptr = &arr[pos];
p = p->Nextptr;
++list_size;
if (arr[pos].Next == -1)
break;
pos = p->Next;
}
*length = list_size;
temp = L; L = L->Nextptr; free(temp);
return L;
}
List Reverse(List L, int reverse_length)
{
List p1, p2, p3, rear;
p1 = L; p2 = L->Nextptr; p3 = p2->Nextptr;
while (reverse_length--) {
p2->Nextptr = p1;
p1 = p2;
p2 = p3;
if(p3) p3 = p3->Nextptr;
}
rear = L->Nextptr;
rear->Nextptr = p2;
L->Nextptr = p1;
return rear;
}
List ReverseList(List L, int length, int reverse_length)
{
if (reverse_length == 1)
return L;
int t;
List head, p, temp;
head = (List)malloc(sizeof(struct Node)); head->Nextptr = L;
p = head;
t = length / reverse_length;
while (t--) {
p = Reverse(p, reverse_length);
}
if (length % reverse_length == 0)
p->Nextptr = NULL;
temp = head;
head = head->Nextptr;
free(temp);
return head;
}
void PrintList( List L )
{
List p;
p = L;
while (p) {
if (!p->Nextptr)
printf("%.5d %d %d\n", p->Address, p->Data, -1);
else
printf("%.5d %d %.5d\n", p->Address, p->Data, p->Nextptr->Address);
p = p->Nextptr;
}
}
int main()
{
int firstAddr;
int N, K;
List L;
scanf("%d %d %d", &firstAddr, &N, &K);
L = ReadList(firstAddr, &N);
L = ReverseList(L, N, K);
PrintList(L);
return 0;
}
题5:
7-5 一元三次方程
给定一个形如ax3+bx2+cx+d=0的一元三次方程。
已知该方程有三个不同的实数根(根与根之差的绝对值≥10−6),且根范围均在[p,q]之间,你需要解出这个方程的三个根。
输入格式:
第一行一个整数T(1≤T≤1000),表示有T组数据
接下来T行,每行6个实数,分别表示a,b,c,d,p,q
数据保证:−102≤p,q≤102,且对于∀x∈[p,q],−106≤f(x)≤106
输出格式:
输出三个实数,表示方程的三个解。
你的答案可以以任意顺序输出。
一个答案被认为是正确的,当且仅当其与标准答案的绝对误差不超过10−6
输入样例:
在这里给出一组输入。例如:
1
1.000000 -5.000000 -4.000000 20.000000 -10.000000 10.000000
输出样例:
在这里给出相应的输出。例如:
-2.000000 2.000000 5.000000
提示1:
样例所给方程的图像如下:
提示2:
对于方程:ax2+bx+c=0(Δ=b2−4ac≥0),它的两个根分别为:x1=2a−b−Δ,x2=2a−b+Δ
思路:
从题中给的提示可以推断出本体采用二分答案,三个二分区间可由两个极值点确定,两个极值点可求导然后用二次方程求根公式得出
血的教训:极值点的sqrt(b*b-3*a*c)被我惯性地写成了sqrt(b*b-4*a*c),导致调试1h仍无果
代码如下:(可以看到明显的调试伤痕)
#include<iostream>
#include<cmath>
#include<iomanip>
using namespace std;
long t;
long double a, b, c, d, p, q;
long double s; long double e; bool mode;
long double ans[3000];
int cnt = 0;
long double f(long double x)
{
return a * x * x * x + b * x * x + c * x + d;
}
long double bsch()
{
long double m;
if (mode)
{
m = (e + s) / 2.0;
while (e - s >= (1e-6) / 2)
{
m = (e + s) / 2.0;
if (f(m) < 0)
{
s = m;
}
else
{
e = m;
}
}
m = (e + s) / 2.0;
return m;
}
else
{
m = (e + s) / 2.0;
while (e - s >= (1e-6) / 2)
{
m = (e + s) / 2.0;
if (f(m) > 0)
{
s = m;
}
else
{
e = m;
}
}
m = (e + s) / 2.0;
return m;
}
}
int main()
{
long double t1, t2;
long double x1, x2, x3;
cin >> t;
for (int i = 0; i < t; i++)
{
cin >> a >> b >> c >> d >> p >> q;
p = p - 1;
q = q + 1;
t1 = (-b + sqrt(b * b - 3 * a * c)) / (3 * a);
t2 = (-b - sqrt(b * b - 3 * a * c)) / (3 * a);
if (a < 0)
{
s = p;
e = t1;
mode = false;
ans[cnt] = bsch();
cnt++;
s = t1;
e = t2;
mode = true;
ans[cnt] = bsch();
cnt++;
s = t2;
e = q;
mode = false;
ans[cnt] = bsch();
cnt++;
}
else
{
s = p;
e = t2;
mode = true;
ans[cnt] = bsch();
cnt++;
s = t2;
e = t1;
mode = false;
ans[cnt] = bsch();
cnt++;
s = t1;
e = q;
mode = true;
ans[cnt] = bsch();
cnt++;
}
}
for (int i = 0; i < cnt; i++)
{
cout << setiosflags(ios::fixed) << setprecision(6) << ans[i] << " ";
if ((i + 1) % 3 == 0)
{
cout << endl;
}
else
{
cout << ' ';
}
}
return 0;
}