因为公布时间是3月22日至3月29日,就为了及时总结复习,我用typora把部分题目总结到一起了,代码均可AC。由于此次只要求使用C++写(哭死,事前没用过C++,还好没涉及到类和对象),故均为C++代码。
2 黑色星期五
#include<iostream>
using namespace std;
int main()
{
int n;
int a[12]={31,28,31,30,31,30,31,31,30,31,30,31};
//int week[7]=[0,1,2,3,4,5,6];
while(scanf("%d",&n)!=EOF)
{
int day=0;
for(int i=1998;i<n;i++)
{
if((i%4==0&&i%100!=0)||(i%400==0))
day+=366;
else
day+=365;
}
int date=(day+4)%7;//计算输入的该年第一天是星期几
int num=0;
if((n%4==0&&n%100!=0)||(n%400==0))//判断该年是否为闰年
a[1]++;
for(int i=0;i<12;i++)
{
if((date+12)%7==5)//判断每个月13号是否为星期五
num++;
date=date+a[i];
}
printf("%d\n",num);
}
}
3整除的尾数
#include <stdio.h>
int getResult(int a, int b, int weishu[])
{
int k=0;
for(int i=0; i<100; i++)//在末尾添加二位数
{
int t=a*100+i;
if(t%b==0)
{
weishu[k++]=i;
}
}
return k;
}
int main()
{
int a, b, weishu[100],count,i;
scanf("%d%d", &a, &b);
count=getResult(a,b,weishu);
for(i=0; i<count; i++)
{
if (i>0)
printf(" ");
printf("%02d", weishu[i]);
}
printf("\n");
return 0;
}
4 谁是老二
#include<iostream>
using namespace std;
int main()
{
int n;
while(cin>>n)
{
int a[n];
int b[n];
int secondmax;
int flag=0;
for(int i=0;i<n;i++)
{
cin>>a[i];
b[i]=a[i];
}
int max=0;
for(int i=0;i<n;i++)//对数组进行排序
{
for(int j=i;j<n;j++)
{
if(b[i]>b[j])
{
int temp=b[i];
b[i]=b[j];
b[j]=temp;
}
}
}
for(int i=n-2;i>0;i--)
{
if(b[n-1]>b[i])
{
secondmax=b[i];//找出第二大
break;
}
if(i==1)
flag=1;
}
if(flag)
cout<<"none"<<endl;
else
{
cout<<secondmax;
for(int i=0;i<n;i++)
{
if(a[i]==secondmax)//输出第二大下标位置
cout<<" "<<i;
}
cout<<endl;
}
}
}
8n层正方形
#include<stdio.h>
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
int a[2*n-1][2*n-1];
int k=1;
while(k<=n)
{
for(int i=k-1; i<=(2*n-1)-k; i++)//二维数组的两端开始向里收缩
for(int j=k-1; j<=(2*n-1)-k; j++)
a[i][j]=k;//不断覆盖外层的赋值,把所在圈数填充完好
k++;
}
for(int i=0;i<(2*n-1);i++)
{
for(int j=0;j<(2*n-1);j++)
{
if(j<2*n-2)
printf("%d ",a[i][j]);
else
printf("%d",a[i][j]);
}
printf("\n");
}
}
}
小数第n 位
#include<iostream>
#include<vector>
using namespace std;
typedef long long ll;
int main(){
ll a;
ll b;
int n;
cin>>a>>b>>n;
while(n - 8 > 0){ //快速减小n,逼近第n位
a *= 1e8; //不能*的太大,否则会溢出
a %= b;
n -= 8;
}
for(int i = 0;i < n + 2;i++){
a *= 10;//①因为之前是对b取余得到的,所以此时的a一定小于吧,对a*10,在对b取余可获得一位数
if(i >= n - 1){ //开始输出三个位
cout<<a/b;
}
a %= b;
}
return 0;
}
34 数列
#include<cmath>
#include<iostream>
#include<cstdio>
using namespace std;
long long a[100000];
int n,m,k=1,t;
int main()
{
a[0]=0;
while(cin>>m>>n)
{
//scanf("%d%d",&m,&n);
for(int i=0; i<100; i++)
{
t=k;
for(int j=0; j<t; j++)
{
a[k]=pow(m,i)+a[j];//每个轮回,都要把pow(m,i)加上去,同时,使用前面已经存在的每个数
if(k==n)
{
cout<<a[k]<<endl;
return 0;
}
else
{
k++;
}
}
}
}
return 0;
}
35 孪生素数
解法:找出不大于N 的所有素数,存储在一维数组中。遍历一位数组,若该素数和后面一位素数之间相差为2,则孪生素数对加一。
输出孪生素数对即可。
36 集合运算
解法:对集合A,B分别进行排序。从小到大进行遍历,两个下标逐渐增加,当A和B中共有时,记录在交集中。把数组B放在数组A中,进行排序,若相同只输出一个,即为并集。遍历数组A,对比在数组B中的每个数,若没有,则输出。
37 区间k 大数查询
解法:根据输入的起始位置,确定截取区间,按照从大到小进行排序,第k大数即为第k-1下标位置上的数。
38 明明的随机数
解法:输入要随机选择的个数N,从大数组中选出N个数,按照从小到大进行排序,输出时,若相同,则只输出一个。
39 数的统计
解法:对于输入的数组,对不同的数字记录下来,排序,依次统计出现的次数
#include<bits/stdc++.h>
using namespace std;
bool cmp(int a,int b)
{
return a<b;
}
typedef struct arr
{
int num;
int count;
};
int main()
{
int n;
while(cin>>n)
{
int beginArr[n];
struct arr arrnum[n];
int k;
for(int i=0; i<n; i++)
{
arrnum[i].count=0;
arrnum[i].num=0;
}
for(int i=0; i<n; i++)
{
cin>>beginArr[i];
}
sort(beginArr,beginArr+n);
arrnum[0].num=beginArr[0];
arrnum[0].count++;
k=0;
for(int i=1; i<n; i++)
{
if(beginArr[i]==beginArr[i-1])
{
arrnum[k].count++;
}
else
{
k++;
arrnum[k].num=beginArr[i];
arrnum[k].count++;
}
}
for(int i=0; i<=k; i++)
{
cout<<arrnum[i].num<<" "<<arrnum[i].count<<endl;
}
}
}
40 数字黑洞
解法:若不为6174,则计算出四位数的最大值,最小值,差,然后比较是否为6174,若否,次数加一,循环上述过程。
//每次把number中的各个位置上的数字分解到temp中,排序之后,通过遍历来构成max和min,max-min来构造新的number
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,i,count=0;
while(cin>>n)
{
int num=n;
while(num!=6174)
{
i=0;
int max=0,min=0;
int number=num;
int temp[4];
memset(temp,0,sizeof(temp));
while(number)
{
temp[i++]=number%10;
number=number/10;
}
sort(temp,temp+4);
for(int j=0;j<4;j++)
{
max=max*10+temp[4-j-1];
min=min*10+temp[j];
}
num=max-min;
count++;
}
cout<<count<<endl;
}
return 0;
}
41 质数的乘积
解法:求出前n个质数,对其进行乘积运算,并对50000进行取模
#include<bits/stdc++.h>
using namespace std;
int prime(long n)
{
if(n==1)
return 0;
if(n==2||n==3)
return 1;
long t=sqrt(n);
for(long i=2; i<=t; i++)
{
if(n%i==0)
return 0;
}
return 1;
}
int main()
{
long long n;
while(cin>>n)
{
long long sum=1;
for(long long i=2;; i++)
{
if(prime(i))
{
sum=sum*i;
sum=sum%50000;
n--;
}
if(n==0)
break;
}
cout<<sum<<endl;
}
return 0;
}
42暗恋
解法:对于输入的二维数组,遍历每个节点,判断由该节点生成的爱情指标的最大值,最后输出最大值。
#include<bits/stdc++.h>
using namespace std;
int love[201][201] = { 0 };
bool isLove(int x, int y,int len)
{
int color = love[x][y];
x++;
y++;
if (love[x][y] != color) return false;
for (int i = 1; i <= len; i++)//判断正方形内是否全部为同一颜色
{
if (love[x - i][y] != color) return false;//y列检查
if (love[x][y - i] != color) return false;//x行检查
}
return true;
}
int main()
{
int r, c;
cin >> r >> c;
for (int i = 1; i <= r; i++)
{
for (int j = 1; j <= c; j++)
{
cin >> love[i][j];
}
}
int max = 1;
bool flag = 0;
for (int i = 1; i <= r; i++)
{
for (int j = 1; j <= c; j++)
{
if (r - i < max)//剩余高度小于最大边长跳出
{
flag = 1;
break;
}
if (c - j < max)//剩余宽度小于最大边长 换行
{
continue;
}
//判断最大边长
int len = 1, x = i, y = j;
while (x < r&&y < c)
{
if (isLove(x, y,len))
{
x++, y++, len++;
if (len>max) max = len;
}
else
{
break;
}
}
}
if (flag)
break;
}
cout << max*max<< endl;
return 0;
}
43 扫雷
解法:对于输入的二位字符型数组,遍历数组。对于安全区,比较周围最多八个数,判断是否有地雷,若有则记录个数。对于雷区,不比较。
#include<bits/stdc++.h>
using namespace std;
char a[100][100];
int m,n;
void bb(int i,int j)
{
int sum=0,x=i-1,y=j-1,x1=i+1,y1=j+1,i1,j1;
if(a[i][j]=='*')
{
cout<<"*";
}
else
{
if(i==0)//判断边界
{
x=0;
}
if(j==0)
{
y=0;
}
if(i==m-1)
{
x1=m-1;
}
if(j==n-1)
{
y1=n-1;
}
for(i1=x; i1<=x1; i1++)//若该点非边界点,判断其周围八个点地雷的个数
{
for(j1=y; j1<=y1; j1++)
{
if(a[i1][j1]=='*')
{
sum++;
}
}
}
cout<<sum;
}
}
int main()
{
int i,j,count=0;
char x;
while(1)
{
cin>>m>>n;
if(m==0&&n==0)
{
break;
}
count++;
for(i=0; i<m; i++)
{
for(j=0; j<n; j++)
{
cin>>x;
if(x==10)//遇到换行,保持j不越界
{
j--;
}
if(x!=10)
{
a[i][j]=x;
}
}
}
cout<<"Field #"<<count<<endl;
for(i=0; i<m; i++)
{
for(j=0; j<n; j++)
{
bb(i,j);
}
cout<<endl;
}
cout<<endl;
}
return 0;
}
44矩阵乘方
解法:给定一个矩阵A,一个非负整数b和一个正整数m,求A的b次方除m的余数。
其中一个nxn的矩阵除m的余数得到的仍是一个nxn的矩阵,这个矩阵的每一个元素是原矩阵对应位置上的数除m的余数。
要计算这个问题,可以将A连乘b次,每次都对m求余,但这种方法特别慢,当b较大时无法使用。下面给出一种较快的算法(用A^b表示A的b次方):
若b=0,则A^b%m=I%m。其中I表示单位矩阵。
若b为偶数,则Ab%m=(A(b/2)%m)^2%m,即先把A乘b/2次方对m求余,然后再平方后对m求余。
若b为奇数,则Ab%m=(A(b-1)%m)*a%m,即先求A乘b-1次方对m求余,然后再乘A后对m求余。
这种方法速度较快,请使用这种方法计算A^b%m,其中A是一个2x2的矩阵,m不大于10000。
#include <iostream>
using namespace std;
int res[2][2];
int sum;
int b, m;
void mutil(int e[][2], int tmp[][2], int m)//计算矩阵相乘,并求出矩阵中每个数对m的求余
{
int t[2][2];
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
sum = 0;
for (int k = 0; k < 2; k++)
{
sum += e[i][k] * tmp[k][j];
}
t[i][j] = sum%m;
}
}
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
e[i][j] = t[i][j];
}
}
return;
}
void runPow(int re[][2], int b, int m)
{
if (b == 0)
{
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
if (i == j) re[i][j] = 1%m;
else re[i][j] = 0;
}
}
return;
}
if (b % 2 == 1)//若b为奇数
{
int tmp[2][2];
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
tmp[i][j] = re[i][j];
}
}
runPow(re, b - 1, m);
mutil(re, tmp, m);
return;
}
else//b为偶数
{
runPow(re, b / 2, m);
mutil(re, re, m);
return;
}
return;
}
int main()
{
cin >> b >> m;
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
cin >> res[i][j];
}
}
runPow(res, b, m);//计算矩阵乘方后的结果
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
cout<<res[i][j]<<" ";
}
cout << endl;
}
return 0;
}
45字符串编辑
解法:
46 S01串
解法:这是一个递归问题,当n=0时,输出为0,当n=1时,输出为1,当n>=2时,输出第n-2个字符,加第n-1个字符。
#include <iostream>
using namespace std;
string fun(int n);
int main()
{
int n;
cin >> n;
cout << fun(n) << endl;
return 0;
}
string fun(int n)
{
if(n == 0)
return "0";
else if(n == 1)
return "1";
else
return fun(n-2) + fun(n-1);
}
47 身份证排序
解法:希望按出生日期对它们进行从大到小排序,如果有相同日期,则按身份证号码从大到小进行排序。
使用结构体,一部分存储出生日期,一部分存储身份证号码。
#include<bits/stdc++.h>
using namespace std;
struct node{
string id;
string birth;
};
int cmp(struct node a,struct node b){
if(a.birth!=b.birth)
return a.birth>b.birth;
else return a.id>b.id;
}
int main(){
int n;
while(cin>>n)
{
struct node number[n];
int i;
for(i=0;i<n;i++)
{
cin>>number[i].id;
number[i].birth=number[i].id.substr(6,8);
}
sort(number,number+n,cmp);
for(i=0;i<n;i++)
{
cout<<number[i].id<<endl;
}
}
return 0;
}
48 回文数
解法:根据进制,算出颠倒数。两个数相加,若为回文数,则返回相加次数,若不是回文数,则继续相加,知道相加次数为30,若还不是回文数,则返回impossible.
#include <iostream>
#include <string>
using namespace std;
int radix, n, sum, flag, a[1001];//定义变量进制数,输入字符串长度,总步数,是否产生回文数,字符串存放的整数数组
string s;
//判断是否是回文数
bool palindromic(int n)
{
for (int i = 1; i <= n / 2; i++)
if (a[i] != a[n - i + 1])
return false;
return true;
}
//两数相加
int add(int n)
{
int c[1001] = { 0 };//定义临时数组,表示两数的和
for (int i = 1; i <= n; i++)//进制数相加
{
c[i] = a[i] + a[n - i + 1] + c[i];//使用同一个数组,进行求回文数
c[i + 1] += c[i] / radix;
c[i] %= radix;
}
if (c[n + 1])//保留进位
n++;
for (int i = n; i >= 1; i--)
{
a[i] = c[i];
}
return n;
}
int main()
{
while(cin>>radix)
{
cin >> s;
n = s.size();
flag=1;
for (int i = 1; i <= n; i++)//将字符串转化为整数数组
{
if (s[i - 1] < 65)
a[i] = s[i - 1] - '0';
else
a[i] = s[i - 1] - 55;
}
while (sum <= 30)
{
if (palindromic(n))
{
cout << "STEP=" << sum << endl;
flag=0;
break;
}
sum++;
n = add(n);
}
if(flag)
cout << "Impossible!" << endl;
}
return 0;
}
50新生舞会
解法:使用结构体
#include <iostream>
#include <string>
using namespace std;
struct student
{
string name;
string num;
char sex;
};
int main()
{
int n;
while(cin>>n)
{
struct student stu[n];
for(int i=0;i<n;i++)
{
cin>>stu[i].name>>stu[i].num>>stu[i].sex;
}
int m;
cin>>m;
string inf1,inf2;
char sex1,sex2;
for(int j=0;j<m;j++)
{
cin>>inf1>>inf2;
for(int i=0;i<n;i++)
{
//cout<<inf1<<inf2<<endl;
if(stu[i].name==inf1||stu[i].num==inf1)
{
sex1=stu[i].sex;
//cout<<inf1<<"sex1"<<sex1<<endl;
}
if(stu[i].name==inf2||stu[i].num==inf2)
{
sex2=stu[i].sex;
//cout<<inf2<<"sex2"<<sex2<<endl;
}
}
if(sex1==sex2)
cout<<"N"<<endl;
else
cout<<"Y"<<endl;
}
}
}
51 班级排名
解法:使用结构体,获取每次的成绩,进行排名
52 铺地毯
解法:使用结构体存储坐标和长度信息,遍历结构体,找到覆盖给出节点的最大值,即为第几张地毯。
#include<cstdio>
#include<cstring>
struct node
{
int a;
int b;
int c;
int d;
}s[10010];
int main()
{
int n,x,lx,y,ly,x1,y1;
while(scanf("%d",&n)!=EOF)
{
memset(s,0,sizeof(s));
for(int i=1;i<=n;i++)
{
scanf("%d %d %d %d",&x,&y,&lx,&ly);
s[i].a=x;
s[i].b=y;
s[i].c=x+lx;
s[i].d=y+ly;
}
scanf("%d %d",&x1,&y1);
if(x1>100000 || y1>100000)
{
printf("-1\n");
continue;
}
int ans=0;
for(int i=1;i<=n;i++)
{
if(s[i].a<=x1 && s[i].b<=y1 && s[i].c>=x1 && s[i].d>=y1)//满足给定的坐标点,落在已有的地毯上
{
ans=i;//因为地毯先后铺上,只要逐个遍历即可找到最上面的地毯
}
}
if(ans)
printf("%d\n",ans);
else printf("-1\n");
}
return 0;
}
52 联系
解法:
53 最小乘积
解法:两组数分别相乘,求出最小值,那么只需要将两个数组进行排序,用一个数组的最大值乘于另外一个数组的最小值。
#include<bits/stdc++.h>
using namespace std;
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
int n;
while(cin>>n)
{
while(n--)
{
int m;
cin>>m;
int num1[m];
int num2[m];
memset(num1,0,sizeof(num1));
memset(num2,0,sizeof(num2));
long long sum=0;
for(int i=0;i<m;i++)
{
cin>>num1[i];
}
for(int i=0;i<m;i++)
cin>>num2[i];
sort(num1,num1+m);
sort(num2,num2+m,cmp);
for(int i=0;i<m;i++)
{
sum+=num1[i]*num2[i];
}
cout<<sum<<endl;
}
}
return 0;
}
54 完美的代价
解法:1. impossible的情况:如果有一个字符出现的次数是奇数次数,而且n是偶数,那么不可能构成回文,如果n是奇数,但是已经有一个字符出现的次数是奇数次数了,那么如果又有一个字符是奇数次数,就不可能构成回文。
- 注意:若n是奇数,计算中间那个字符交换的次数的时候,不需要模拟把这个数移动到中间去,因为移动到中间的话——假设有一对数都在左边或者都在右边,那么交换成回文的时候就要经过中间,就会每次多加了1,而这个1是没有必要的,因为可以所有的回文移动完了之后再把这个独立的数移动过去,才能保证交换次数最少。
#include <bits/stdc++.h>
using namespace std;
char str[8005];
int main() {
int n, r, ans = 0, temp = 0;
scanf("%d%s", &n, str);
r = n - 1;//r指向字符串需要交换的末尾下标
for (int i = 0; i < n / 2; i++) {//i指针从头遍历到中间字符
for (int j = r; j >= i; j--) {//j指针从后面往前一直到i寻找和str[i]相同的str[j]
if (j != i) {
if (str[i] == str[j]) {
for (int k = j; k < r; k++)//把str[j]换到str[r]处
swap(str[k], str[k + 1]);
ans += r - j;//统计交换次数
r--;//往前推进
break;
}
}
else {//如果找不到相同的
if (!(n & 1) || temp) {//impossible的两种情况, temp表示出现奇数次的字符。
printf("Impossible\n");//n&1,与运算,可以判断n是否为偶数,,如果是偶数,n&1返回0;否则返回1,为奇数。
return 0;
}
temp = 1;
ans += n / 2 - i;//移动到中间需要的交换次数(距离即为交换次数),不需要现在交换过去,最后交换
}
}
}
printf("%d\n", ans);
return 0;
}
56 纪念品分组
解法:进行排序,从小到大两端遍历,若和不大于给定的值,则次数加一,两端进位。若大于给定的值,只有大端进位,次数加一。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 30005;
int a[maxn];
int main ( )
{
int w, n, ans = 0;
cin>>w>>n;
for ( int i = 0; i < n; i ++ )
cin>>a[i];
sort ( a, a+n ); //贪心
for ( int i = 0, j = n-1; i <= j; )
{
if ( a[i]+a[j] <= w ) //要么取两个,要么就把最大的取了
i ++, j --;
else
j --;
ans ++;
}
cout<<ans<<endl;
return 0;
}
57 旅行家的预算(难)
解法:思路:是找在最大行驶距离内寻找比当前便宜的加油站,然后判断是否能一次到达,不能的话先加满,然后一个一个判断直到剩下的油量不足到下一个加油站就加油,加适量。
于是有以下2 situations:
1.这个站点j 就是pos
再细分两种情况:
1.从pos就可以走到终点
于是我们把油加到刚好到达终点即可
cost += ((d[i] - d[pos]) / d2 - remain)*p[pos];就得到了最后答案。
remain是当前剩余的油
2.从pos不能一把走到终点
于是,从当前位置走,走到哪里加油都不够在pos这里加油划算。
所以加满。
2.这个站点j 是在pos后面的某个站点
也有两种情况
1.当前剩余的油remain不够走到j
于是我们,把油加来刚好能够走到j就行了。(因为j这里好好便宜!)
2.剩余的油remain足够,直接开过去就行了。
#include<iostream>
#include<algorithm>
#include<iomanip>
using namespace std;
double d[10000], p[10000]; //出发点每升汽油的价格p
int main()
{
ios::sync_with_stdio(false); //取消cin在stdin上的同步,增加cin的读取效率
double d1, c, d2;
int n; //沿途油站数目
cin >> d1 >> c >> d2 >> p[0] >> n;
d[n + 1] = d1; //第n个油站后即为最后的站点
for (int i = 1; i <= n; i++) //输入每一个油站离出发点的距离以及每个站点汽油的价格
{
cin >> d[i] >> p[i];
}
int pos = 0;
double remain = 0, cost = 0;
do
{
bool found = false; //判定能不能到达
for (int i = pos + 1; i <= n + 1 && d[i] <= d[pos] + c*d2; i++) //循环判断加满油能不能到达下一个加油站
{
if (p[i] < p[pos]) //判断下个站点汽油的价格是不是比这个pos站点汽油的价格小
{
if (d[pos] + remain*d2 >= d[i]) //若是剩余的油足够,刚好开过去
{
remain -= (d[i] - d[pos]) / d2; //剩余的油减少,减少量就是从一个站点到下一个站点用到的油
}
else //剩余的油不够
{
cost += ((d[i] - d[pos]) / d2 - remain)*p[pos]; //还需要加的油花费的价钱,不用加满
remain = 0; //到达下一个站点恰好没油了,所以剩余汽油量清0
}
pos = i;
found = true;
break;
}
}
if (!found)
{
cost += (c - remain)*p[pos]; //不能到达前花费了多少钱
remain = c - (d[pos + 1] - d[pos]) / d2; //还剩多少油
if (remain >= 0) pos++; //小于0,油根本不够到达下一个站点,大于0,代表可以去下一个加油站
else
{
cout << "No Solution";
return 0;
}
}
} while (pos <= n); //循环条件:没到达终点
cout.setf(ios::fixed); //以定点形式显示浮点数
cout << setprecision(2) << cost;
}
58 盾神与积木游戏
解法:要完成全部的作品,则每次要花最少的积木数,拼成尽可能的得到多的作品,
这里用结构体设置三个字段:该孩子现有积木,拼成需要的积木,还差几个积木
要拼成尽可能多的作品,得到更多的积木,则需要将字段3由小到大的开始拼
对字段3进行升序排序,将每次剩余多少积木记录,判断,即可。
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct node{
int having;
int need;//拼完一个积木作品所需的积木个数
int mul;//差 = need - having
};
bool cmp(node a,node b){
return a.mul<b.mul;//升序
}
int main()
{
int m;
int n;
cin>>m;
int having,need;
for(int i=0;i<m;i++){
cin>>n;
vector<node>v;
for(int j=0;j<n;j++){
node a1;
cin>>a1.having>>a1.need;
a1.mul=a1.need-a1.having;
v.push_back(a1);
}
sort(v.begin(),v.end(),cmp);//按照 need - having 的结果进行升序排序
int rest=0;//剩余的积木数
int flag=0;//够不够的标志
for(int j=0;j<n;j++){
// cout<<"rest="<<rest<<" "<<v[j].having<<","<<v[j].need<<","<<v[j].mul<<" ";
if(v[j].mul<=0){//积木数大于或等于,不用加积木,拼成功,推翻
rest+=v[j].having;
}else{
rest-=v[j].mul;//扣掉积木给小朋友
if(rest>=0){//积木数够
rest+=v[j].need;//拼成功,推翻
}else{//积木数不够直接退出
flag=1;
break;
}
}
}
if(flag==1)cout<<"NO"<<endl;
else cout<<"YES"<<endl;
// if(i<m-1) cout<<endl;
}
return 0;
}
60 瓷砖铺路
解法:使用递归,每次瓷砖加一或者加2,每次加到n,则次数累加,若大于n ,则不成功,返回
#include<iostream>
using namespace std;
int n;//瓷砖的长度
int ret = 0;//统计方案数
//递归
void dfs(int t){
//如果当前层大于n,则退出
if (t > n)
return;
//当前层等于n,计数
if (t == n){
ret++;
return;
}
//递归+1的
dfs(t + 1);
//递归+2的
dfs(t + 2);
}
int main()
{
cin >> n;
//从0开始递归
dfs(0);
cout << ret << endl;
return 0;
}
61 求先序排列
解法:按照中序和后序的关系,每次输出先序排列的一个数
#include<bits/stdc++.h>
using namespace std;
void preOrder(string in, string post)
{
if ((int)in.length() > 0)
{
char c = post[(int)post.length() - 1];
cout << c;//每次输出先序排序的根节点
int k = in.find(c);
preOrder(in.substr(0, k), post.substr(0, k));//前部进行先序
preOrder((in.substr(k + 1)), post.substr(k, post.length() - k - 1));//后部进行排序
}
}
int main()
{
string inOrder, postOrder;//中后
cin >> inOrder >> postOrder;
preOrder(inOrder, postOrder);
cout<<endl;
return 0;
}
62 FBI树
解法:进行深度优先遍历,按照后续遍历,先访问左子树,再访问右子树,再访问根节点
#include<bits/stdc++.h>
using namespace std;
char a[2500];
void FBI(int i,int j)
{
int mid;
int I,B;
if (i<=j)
{
mid=(i+j)/2;
I=0;
B=0;
if (i!=j)//先访问左子树,再访问右子树,再访问根节点
{
FBI(i,mid);//分出左子树
FBI(mid+1,j);//分出右子树
}
for (int m=i; m<=j; m++)
if (a[m]=='0') B++;
else I++;
if (B>0 && I>0) printf("F");
else if (B) printf("B");
else printf("I");
}
}
int main()
{
int n;
cin>>n;
cin>>a;
FBI(0,pow(2,n)-1);
return 0;
}