题目分类:
- 1.高精度运算
- 2.最短路径
- 3.DFS模拟
1.高精度立方
从控制台输入一个合法数字,打印其立方
• 例如
• 输入123456789
• 输出1881676371789154860897069
• 基本编码能力、消耗时间
题解:
先进行计算,第二步处理进位问题。为方便进位操作,高精度存储时低位在前,高位在后。高精度乘法:1.i位与j位相乘,数字会放在i+j位置上。 2.处理每一位的进位问题。
模板见:【链接】
加法:【链接】
#include<cstdio>
#include<iostream>
#include<map>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
string s1;
int a[99999];
int b[99999],c[99999];
int main()
{
getline(cin,s1);
fill(a,a+99999,0);
fill(b,b+99999,0);
fill(c,c+99999,0);
int k=0,n=s1.size();
for(int i=n-1;i>=0;i--)
a[k++]=s1[i]-'0';
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
b[i+j]+=a[i]*a[j];
//处理进位,位数与0的双检测
k=0;
while(b[k]!=0||k<(n-1)+(n-1))
{
if(b[k]>10)
{
b[k+1]+=b[k]/10;
b[k]=b[k]%10;
}
k++;
}
for(int i=0;i<n;i++)
for(int j=0;j<k;j++)
c[i+j]+=a[i]*b[j];
//处理进位,位数与0的双检测
int k2=0;
while(c[k2]!=0||k2<(n-1)+(k-1))
{
if(c[k2]>10)
{
c[k2+1]+=c[k2]/10;
c[k2]=c[k2]%10;
}
k2++;
}
for(int i=k2-1;i>=0;i--)
printf("%d",c[i]);
return 0;
}
//4 235
//34 12 5 5
2.最短路径
从控制台输入n+1 行,前n 行每行3 个整数,形如“A B d”,表示从节点A 到节点B 距离为d(双向)。第n+1 行形如“A B”,表示求A 到B 的最短距离。输出此最短距离。
• 例如:
1 42 3
42 789 4
1 789 9
1 789
输出
7
• BFS、动态规划、剪枝、图
题解:
这个也迷惑行为,因为没见过题目,也不大清楚究竟考点在哪。。。01规划??反正看到题目想到的也是Djistra算法。。。这里用map作为去重找点的方法,并用索引给边权,原因是直接遍历比较大。
#include<cstdio>
#include<iostream>
#include<string>
#include<cmath>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
using namespace std;
int t1,t2,i=3,j=1;
int t,start,end1,a[500][500];
map<int,int> mp;
int main()
{
while(i>0)
{
scanf("%d %d %d",&t1,&t2,&t);
if(mp[t1]==0) mp[t1]=j++;
if(mp[t2]==0) mp[t2]=j++;
a[mp[t1]][mp[t2]]=a[mp[t2]][mp[t1]]=t;
i--;
}
scanf("%d %d",&start,&end1);
start=mp[start];
end1=mp[end1];
int n=j-1;
int vis[n+1],dis[n+1];
//初始化
fill(vis,vis+n+1,0);
fill(dis,dis+n+1,9999999);
dis[start]=0;
//printf("%d",n);
for(int i=0;i<n;i++)
{
//寻找最小的点
int maxv=99999999,maxi;
for(int j=1;j<=n;j++)
if(dis[j]<maxv&&vis[j]==0)
{
maxv=dis[j];
maxi=j;
}
//设置为访问点
vis[maxi]=1;
//printf("%d \n",maxi);
for(int j=1;j<=n;j++)
if(dis[j]>dis[maxi]+a[maxi][j]&&vis[j]==0)
dis[j]=dis[maxi]+a[maxi][j];
}
printf("%d\n",dis[end1]);
return 0;
}
3.四则运算问题
从控制台输入一行,形如“n A1 A2 A3 … An B”。其中n代表操作数总数,A1~An 表示n 个操作数。B 代表目标数字。在此n 个操作数中以任意顺序插入n-1 个四则运算操作符,不能插入括号,形成的表达式能否得到B?能——输出1,不能——输出0。操作数和目标数字是整数,整数大小限制在32 位有符号整数范围内。
• 例如:
4 75 4 18 8 21
输出1 (75 / 4 + 18 / 8 = 21)
• 表达式求值、DFS(回溯)、栈、树
二刷代码
用一个vector代替栈,将*/先进行计算,再计算对应的+ -,总体使用dfs框架。需要注意21计算时需要浮点的精度四舍五入才能得到运算结果。
#include<cstdio>
#include<iostream>
#include<map>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
int a[99999],n,num,flag=0;
//1.2 +- 3.4 */
int fuhao[4]={-1,-2,-3,-4};
vector<double> b,st,tmpst,bres;
void print(int cnt)
{
printf("%d",a[0]);
for(int i=0;i<bres.size();i++)
{
if(bres[i]==-1) printf("*");
else if(bres[i]==-2) printf("/");
else if(bres[i]==-3) printf("+");
else printf("-");
printf("%d",a[i+1]);
}
printf("=%d\n",cnt);
}
void dfs(int t)
{
if(t==n)
{
tmpst.clear();
bres.clear();
bres=b;
tmpst.push_back(a[0]);
//printf("%d %d\n",b.size(),t);
for(int i=0;i<n;i++)
{
if(b[i]>=-2)
{
//*,/
if(b[i]==-1) tmpst[tmpst.size()-1]*=a[i+1];
else if(b[i]==-2) tmpst[tmpst.size()-1]/=a[i+1];
}
else
{
tmpst.push_back(b[i]);
tmpst.push_back(a[i+1]);
}
}
//printf("111\n");
double cnt=tmpst[0];
for(int i=1;i<tmpst.size();i+=2)
{
if(tmpst[i]==-3) cnt+=(double)tmpst[i+1];
else cnt-=(double)tmpst[i+1];
}
if(cnt==num)
{
flag=1;
printf("1\n");
print(cnt);
}
b.pop_back();
return ;
}
for(int i=0;i<4;i++)
{
b.push_back(fuhao[i]);
dfs(t+1);
}
b.pop_back();
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
scanf("%d",&num);
dfs(1);
if(flag==0)
printf("0\n");
return 0;
}
//4 235
//34 12 5 5
题解:
个人感觉是个dfs的模拟题,可以用两个数组去做。我这个emmmm反正写是写出来了,但感觉不是很好。原博主的似乎是个模板。类似于表达式的双栈解决。但感觉代码量相差不太大。
#include<cstdio>
#include<iostream>
#include<string>
#include<cmath>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
using namespace std;
int t1,t2,i=3,j=1;
int n,k,a[500];
int b[4]={0,1,2,3};
vector<float> res,res2,a2,ans2,c;
void dfs(int i)
{
if(i==n-1)
{
int vis[a2.size()],ans=0;
fill(vis,vis+a2.size(),1);
c.clear();
res.clear();
res2.clear();
for(int i=0;i<n;i++)
c.push_back(a[i]);
//先做乘除法,并通过vis给出剩余数字
for(int j=0;j<a2.size();j++)
if(a2[j]==2){
c[j+1]=c[j]*c[j+1];
vis[j]=0;
}
else if(a2[j]==3)
{
c[j+1]=c[j]/c[j+1];
vis[j]=0;
}
//剩余数字放入res
for(int j=0;j<a2.size();j++)
if(vis[j]==1){
res.push_back(c[j]);
res2.push_back(a2[j]);
}
res.push_back(c[n-1]);
//做加减法
for(int j=0;j<res2.size();j++)
{
if(res2[j]==0) res[j+1]=res[j]+res[j+1];
else res[j+1]=res[j]-res[j+1];
}
if(res[res.size()-1]==k)
{
for(int j=0;j<n-1;j++)
{
cout<<a[j];
if(a2[j]==0)cout<<"+";
else if(a2[j]==1) cout<<"-";
else if(a2[j]==2) cout<<"*";
else if(a2[j]==3) cout<<"/";
}
cout<<a[n-1]<<"="<<res[res.size()-1]<<endl;
}
return ;
}
for(int j=0;j<=3;j++)
{
a2.push_back(b[j]);
dfs(i+1);
a2.pop_back();
}
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
scanf("%d",&k);
dfs(0);
return 0;
}
//4 75 4 18 8 21