一、优秀的拆分
题目描述:


解题思路:
给定正整数a,计算不超过a的最大的2的正整数次幂h,返回剩余部分a-h,直到返回部分等于0为止。
参考代码:
#include<bits/stdc++.h>
using namespace std;
//计算不超过a的最大的2的正整数次幂
int f(int a)
{
int h=(int)(log(a)/log(2));
h=(1<<h);
cout<<h<<' ';
return a-h;
}
int main()
{
freopen("power.in","r",stdin);
freopen("power.out","w",stdout);
int a;
cin>>a;
if (a%2==1) //奇数不存在优秀拆分
cout<<-1;
else
while(a>0)
a=f(a);
}
二、直播获奖
题目描述:


解题思路:
(1)采用桶排序思想,对所有选手成绩进行计数,成绩的取值范围是0~600。
(2)根据获奖率和已评出的选手成绩,计算当前获奖分数线。
参考代码:
#include<bits/stdc++.h>
#define N 601
#define M 100000
using namespace std;
int t[M];
int h[N];
int main()
{
freopen("live.in","r",stdin);
freopen("live.out","w",stdout);
int n,w;
int i,j,k,p,r;
cin>>n>>w;
//计算计划获奖人数
for (p=1;p<=n;p++)
{
r=p*w/100;
if (r==0)
t[p-1]=1;
else
t[p-1]=r;
}
//输入当前成绩,输出获奖分数线
for (i=0;i<n;i++)
{
cin>>r;
h[r]++; //计算当前成绩的次数
j=N;
k=h[j];
while(k<t[i]) //计算获奖分数线
{
j--;
k=k+h[j];
}
cout<<j<<' ';
}
}
三、表达式
题目描述:



解题思路:
(1)构建逻辑表达式计算树(可采用静态数组),根据表达式各变量的初始值计算表达式结果。
(2)针对每一次变量值修改,沿该叶子节点往上计算,通过比较每次计算结果,判断表达式最终结果是否改变,并输出表达式的值。
参考代码:
#include<bits/stdc++.h>
using namespace std;
char expr[1000001];
int t[500000][5];
int s[100000][2];
int n, q, k, m;
//构建表达式计算树
int build()
{
int j=-1;
int i=0;
int x,l,r;
k=0;
//读表达式,构建二叉树(静态数组)
while(expr[i]!=0)
{
if ( expr[i]<='9' && expr[i]>='0' )
{
x=0;
while( expr[i]<='9' && expr[i]>='0' )
{
x = x*10 + expr[i]-'0';
i++;
}
j++;
s[j][0]=x-1;
}
else if (expr[i] == '&')
{
t[n+k][4]=-1;
l=s[j-1][0];
r=s[j][0];
t[n+k][1]=-1;
t[n+k][2]=l;
t[n+k][3]=r;
t[l][1]=n+k;
t[r][1]=n+k;
t[n+k][0] = (t[l][0] && t[r][0]);
j--;
s[j][0]=n+k;
k++;
i++;
}
else if (expr[i] == '|')
{
t[n+k][4] = -2;
l=s[j-1][0];
r=s[j][0];
t[n+k][1]=-1;
t[n+k][2]=l;
t[n+k][3]=r;
t[l][1]=n+k;
t[r][1]=n+k;
t[n+k][0] = (t[l][0] || t[r][0]);
j--;
s[j][0]=n+k;
k++;
i++;
}
else if (expr[i] == '!')
{
t[n+k][4] = -3;
l=s[j][0];
t[n+k][1]=-1;
t[n+k][2]=l;
t[n+k][3]=-1;
t[l][1]=n+k;
t[n+k][0] = 1-t[l][0];
s[j][0]=n+k;
k++;
i++;
}
else
i++;
}
return t[n+k-1][0];
}
//改变变量真值,计算表达式运算结果
void calc(int h)
{
int p=t[h][1];
int l,r,v;
int d=0;
s[d][0]=h;
s[d][1]=1-t[h][0];
//从节点r的父节点开始,往上计算
while(1)
{
if (t[p][4]==-1)
{
l=t[p][2];
r=t[p][3];
if (s[d][0]==l)
v= s[d][1] && t[r][0];
else
v= t[l][0] && s[d][1];
}
else if (t[p][4]==-2)
{
l=t[p][2];
r=t[p][3];
if (s[d][0]==l)
v= s[d][1] || t[r][0];
else
v= t[l][0] || s[d][1];
}
else
v= 1-s[d][1];
if (v==t[p][0])
{
cout<<m<<endl;
break;
}
else if (t[p][1]==-1)
{
cout<<v<<endl;
break;
}
else
{
d++;
s[d][0]=p;
s[d][1]=v;
p=t[p][1];
}
}
}
int main()
{
freopen("expr.in","r",stdin);
freopen("expr.out","w",stdout);
gets(expr);
cin>>n;
for (int i=0;i<n;i++)
{
cin>>t[i][0];
t[i][2]=-1;
t[i][3]=-1;
t[i][3]=0;
t[i][4]=0;
}
m=build();
cin>>q;
int r;
for (int i=0;i<q;i++)
{
cin>>r;
calc(r-1);
}
}
四、方格取数
题目描述:


解题思路:
到达任一方格的最大整数和,取决于该方格与三个邻近方格(左、上、下)相加的最大值。
(1)对于第1列,仅考虑向下累加;
(2)对于其它列,先计算向右累加,然后计算向下,向上累加,比较三个方向的累加值,取最大值。
参考代码:
#include<bits/stdc++.h>
using namespace std;
int a[1000][1000];
long long b[1000][1000];
long long c[1000];
long long d[1000];
int n,m;
//向右方向计算
void right(int j)
{
for (int i=0;i<n;i++)
b[i][j]=b[i][j-1]+a[i][j];
}
//向下方向计算
void down(int j)
{
d[0]=b[0][j];
for (int i=1;i<n;i++)
if (b[i-1][j]>d[i-1])
d[i]=b[i-1][j]+a[i][j];
else
d[i]=d[i-1]+a[i][j];
}
//向上方向计算
void up(int j)
{
c[n-1]=b[n-1][j];
for (int i=n-2;i>=0;i--)
if (b[i+1][j]>c[i+1])
c[i]=b[i+1][j]+a[i][j];
else
c[i]=c[i+1]+a[i][j];
}
//比较三个方向的最大值
void comp(int j)
{
for (int i=0;i<n;i++)
{
if (c[i]>b[i][j])
b[i][j]=c[i];
if (d[i]>b[i][j])
b[i][j]=d[i];
}
}
int main()
{
freopen("number.in","r",stdin);
freopen("number.out","w",stdout);
cin>>n;
cin>>m;
for (int i=0;i<n;i++)
for (int j=0;j<m;j++)
cin>>a[i][j];
//第1列累加
long long s=0;
for (int i=0;i<n;i++)
{
b[i][0]=s+a[i][0];
s=b[i][0];
}
//其它列计算
for (int j=1;j<m;j++)
{
right(j);
down(j);
up(j);
comp(j);
}
//输出最后格子的值
cout<<b[n-1][m-1];
}
本文介绍了四个算法问题的解决方案:优秀拆分涉及找到最大2的幂次并计算剩余部分;直播获奖利用桶排序计算获奖分数线;表达式计算涉及构建逻辑表达式树并动态更新结果;方格取数则关注二维矩阵中最大整数和的计算策略。这些题目涵盖了数学逻辑、数据处理和算法设计等核心概念。
1344

被折叠的 条评论
为什么被折叠?



