合肥工业大学oj 算法实训(1)【此后无良辰】

先暂时写必做30道题 只放思路和核心部分

(写的繁琐但易理解)

觉得有用的看官点个赞可好?

(citrl + F 查找功能)

1.合法栈输出1060

在这里插入图片描述
记住数据输入是以EOF结束输入
基本思路 :回溯暴力
从1开始到n
每一步只有三种可能
1.出栈
2.入栈
3.不进不出,对栈进行出栈处理

map<string,int> Map;//哈希表功能

void dfs(int x,stack<int> q1,vector<int> tem)
{
        if(x==m+1)//终止条件
        {
                while(!q1.empty())
                {
                        tem.push_back(q1.top());
                        q1.pop();
                }
                string s; 
                for(int i =0;i<tem.size();++i)
        	{
        		if(tem[i]==10)
        		s=s+"10#";
        		else 
        		{
        			char c=tem[i]+'0';
        			s=s+c;
        		}//此部分为记录答案形式为string存在map里面
        	}
        	if(Map.find(s)==Map.end())//map的防止重复
                {
			ans.push_back(tem);
			Map[s]=1;
                }
		return ;
        }
        for(int i= 0;i<=2;++i)
        {
                if(!i) // 出栈
                {
                	vector<int> tem1;
			tem1=tem; 
                        tem.push_back(x);
                        dfs(x+1,q1,tem);
                        tem=tem1;
                }
                else if(i==1)// 入栈
                {
                	stack<int> q;
                	q=q1;
                        q1.push(x);
                        dfs(x+1,q1,tem);
                        q1=q;
                }
                else if(!q1.empty()) //数字不进不出,对栈处理
                {
                	vector<int> tem1;
					tem1=tem;
                	tem.push_back(q1.top());
                        q1.pop();
                        dfs(x,q1,tem);
                        tem=tem1;
                }
        }
}

2.简单的最小数1065

在这里插入图片描述
注意 排序从大到小,然后去掉是不行的,因为一个数在占高位的权重你是没办法做到比较的
给个例子
8 3
16347895 从大到小排序去掉 16345
正确答案 13475
基本思路:贪心思想,一共有n-k位数剩余
从最高位开始 每次选最小数直到选出所有

第一次选第一位的区域为0-k(记选第i位的数),然后k减去对应的值
随后第二次选的区域为[i+1,i+1+k] ,
依次类推直到选出所有的数
记得if(s.length()-j==k) return; 剩下的数可以全部删掉肯定全部删掉最优

#include <iostream>
#include <cstdlib>
#include <cassert>
using namespace std;
string ans="";

int findmin(string s)
{
        int minn=s[0]-'0',id=0;
        for(int i = 0;i<s.length();++i)
        {
                if(minn>(s[i]-'0'))
                {
                        minn=s[i]-'0';
                        id=i;
                }
        }
        return id;
}

void getRemain(string s,int k,int weishu)
{
        int j=0;
        for(int i = 0;i<weishu;++i)//选出n-k位数
        {
                if(s.length()-j==k) return;
                string s1= s.substr(j,k+1);//可选的区间 更新
                j=j+findmin(s1);
                ans=ans+s[j];
                ++j;
                k=k-findmin(s1);
        }
}

int main()
{
	int n,k;
    	while(scanf("%d%d",&n,&k)!=EOF)
	{
		string s;cin>>s;
		ans="";
		getRemain(s,k,n-k);
		 while(ans[0]-'0'==0&&ans.size()>=2)//去前导0
		{
			ans=ans.substr(1);
		} 
		cout<<ans<<endl;
	};
}

3.简单的统计1156 (大水题过)

在这里插入图片描述
标注一下答案要换行

4.幸运数字1240(大水题)

在这里插入图片描述

bool check(int x)
{
	int mod=0;
	int tem=x; 
	while(x)
	{
		mod+=x%10;
		x/=10; 
	}
	if(tem%mod==0) return 1;
	else return 0; 
}

5.矩阵乘法1209

在这里插入图片描述
基本思路:基本题目,推荐struct 重载运算符做

struct lth
{
	int num[101][101];
	lth * operator * (lth a)const
	{
		lth * tem= new lth;
                for(int i=1;i<=n;++i)
                        for(int j=1;j<=m;j++)
                {
                        for(int o=1;o<=k;++o)
                        {
			tem->num[i][j]+=num[i][o]*a.num[o][j];//乘法
			}
		}        
                return tem;
	}
        bool operator == (lth  a)const
        {
                for(int i=1;i<=n;++i)
                        for(int j=1;j<=m;j++)
                if(a.num[i][j]!=num[i][j]) return 0;
                return 1;
        }
};

6.画菱形1249(大水题过)

基本模拟根据循环变量输出
注意每个数据相差一个换行
行末不能多余空格

(去他个小杰瑞)

7.面试1252

注意:行末不能有空格(去他个小杰瑞)

for(int j=0;j<n-1;j++)
		{
			cout<<a[((j-k)+n)%n]<<" ";
		}
	

8.Three1262(图片还没好,于是我百度)

//自己找四片纸,找规律即可
#include<iostream>
using namespace std;
 
int T;
int main(){
    cin >> T;
    while(T--){
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        if((a == 1 && b == 2) || (a == 2 && b == 3) || (a == 3 && b == 1)) cout << "YES" << endl;
        else if((c == 1 && d == 3) || (c == 2 && d == 1) || (c == 3 && d == 2)) cout << "YES" << endl;
        else cout << "NO" << endl;
    }
    return 0;
}
 
//presented by 大吉大利。今晚AC

9.Alice的车牌号1279

在这里插入图片描述
题目的问题
答案应该是以下(英文’与中文’)
车牌号中,样例给的是全角’,题目要求输出的是半角’

	if(!sym) cout<<": Yes, I like it!"<<endl;
		else cout<<": No, it's terrible!"<<endl;

10.最低等级1283 进制转换

string itoa_to(int tem)
{
	string s;
	while(tem)
	{
		s=s+char(tem%2+'0');
		tem/=2;
	}
	return s; 
} 

11.中位数1316(大水题)

排序找
注意保留2位小数

 printf("%.2f\n",ans);

12.一加二减三1337(大水题过)

13.最短路1328

基本图论题
在这里插入图片描述
输入莫名其妙的麻烦复制粘贴就好了
开longl ong
这里要用链式前向星(矩阵会爆掉)【不会的去百度下基本储存图论吧】

struct lth
{
        ll u,v,next,first,w;
}e[10001000];

算法因为单元最短路径 且为密集图 使用Djstla

void Djstla(int x)
{
        priority_queue<ll,vector<ll>,greater<ll> > q;
        dis[x]=0;q.push(x);
        while(!q.empty())
        {
                ll u=q.top();q.pop();
                if(!tag[u])
                {
                	//cout<<u;
                        tag[u]=1;
                        for(ll i=e[u].first;i;i=e[i].next)
                        {
                                ll v=e[i].v,w=e[i].w;
                                dis[v]=min(dis[v],dis[u]+w);
                                //cout<<v<<endl;
                                q.push(v);
                        }
                }
        }
}

14.回文数1331

在这里插入图片描述
挺麻烦的一道题目
建议这用开存储

struct lth
{
	int num[100]={0};
};

字符串处理单个字符不能超过10,会出大问题

			for(int i=0;i<now;++i)
			{
				e1->num[i]=e2.num[now-i-1];	//反转
			}
			for(int i= 0;i<now;++i)//高精度加法
			{
				e2.num[i]+=e1->num[i];
				e2.num[i+1]+=e2.num[i]/10;
				e2.num[i]%=10; 
			}
			while(e2.num[now])//最高位进位问题
			{
				e2.num[now+1]+=e2.num[now]/10;
				e2.num[now]%=10;
				++now;
			}

15.蛇形阵1332

高中时候就做过这道题,巨麻烦
我一直想问候全网第一个出这个题目的人
(**********************************)
但这道题有很多限制还比较简单
模拟题没算法就不贴出来了(最好自己做,不然考试考到就GG)
注意:printf("%4d",f[i][j]);输出格式
在这里插入图片描述

16.一加二减三1337(大水题过)重了

17.六六六星人1341

在这里插入图片描述
这道题就是单纯的排序
推荐使用

sort(e + 1, e + 1 + n, cmp);//重载cmp
struct lth
{
    string s;
    int id = 0;
};
bool cmp(lth a, lth b)
{
    string s1; string s2;
    int id1=0, id2=0;
    for (int i = 0; i < a.s.length(); ++i)
    {
        if (a.s[i] <= '9' && a.s[i] >= '0')
        {
            s1 = a.s.substr(i);
            id1 = i;
            break;
        }
    }
    for (int i = 0; i < b.s.length(); ++i)
    {
        if (b.s[i] <= '9' && b.s[i] >= '0')
        {
            s2 = b.s.substr(i);
            id2 = i;
            break;
        }
    }
    //寻找数字分界点
    // id没有任何含义,只是为了return 时可以比较a,b,从而不会报错
    if (s1.length() != s2.length())
    {
        if (s1.length() > s2.length()) { b.id = 1; a.id = 0; return b.id < a.id; }
        else { b.id = 0; a.id = 1; return b.id < a.id; }
    }
    else
    {
        for (int i = 0; i < s1.length(); ++i)
        {
            int a1 = s1[i] - '0', b1 = s2[i] - '0';
            if (a1 == b1) continue;
            if (a1 > b1) { b.id = 1; a.id = 0; return b.id < a.id; }
            else { b.id = 0; a.id = 1; return b.id < a.id; }
        }
    }
    s1 = a.s.substr(0, id1);
    s2 = b.s.substr(0, id2);
    if (s1.compare(s2) > 0) { b.id = 1; a.id = 0; return b.id < a.id; }
    else { b.id = 0; a.id = 1; return b.id < a.id; }
}

18.First Blood1343(数论题)

没啥好说的,这些数论题能否做出来真的很靠数学敏感
在这里插入图片描述
因为本题目中要求最小公倍数的最大值,那么可以直接从N向前看,找三个连续的互为质数的数,那么它们的乘积便是1~N最小公倍数的最大值。
有以下二种情况。
(1)当N为奇数时,那么N,N-1,N-2互为质数,很明显NN-1N-2是1~N最小公倍数的最大值。
(2)当N为偶数时,且能被3整除时,N-1,N-2,N-3互质,此时N-1N-2N-3是1~N最小公倍数的最大值
当N为偶数时,但不能被3整除时,N,N-1,N-3互质,此时NN-1N-3是1~N最小公倍数的最大值。
注意:开long long

19.求和1344

在这里插入图片描述
k为半个周期
一个周期的值为 k*k

	   long long tem = n / (2 * k);
        ans = tem * (k * k);
        //超出周期的暴力算

分界线-----------------------------------------------分界线
接下来比较简单 浅水区

20.数71345

在这里插入图片描述
模拟题 没啥可说的
大胆的暴力写

21.进制转换II 1602

将2进制数转换成10进制数

	string s;
    cin >> s;
    ll ans = 0;
    for (int i = 0; i < s.length(); ++i)
        if (s[i] - '0' == 1) ans += pow(2, i);

22.进制转换IV 1604

将8进制数转换成10进制数

string itoa_to(int tem)
{
    string s;
    while (tem)
    {
        s = s + char(tem % 2 + '0');
        tem /= 2;
    }
    return s;
}

for (int i = 0; i < s.length(); ++i)
        if (s[i] - '0' == 1) ans += pow(8, i);
    string s1 = itoa_to(ans);

23.数字反转II1607

给出一个有符号整数N,你需要将这个整数中每位上的数字进行反转。

string s;
    cin >> s;
    int sym = 0;
    if (s[0] == '-') {
        sym = 1; s = s.substr(1);
    }
    reverse(s.begin(), s.end());
    if (sym) cout << "-";
    cout << s;

24.数据检查1629

 double tem = i;
        double tem1 = sqrt(tem);
        int tem2 = sqrt(tem);
        if(tem1==tem2)
          ans++;

25.按序查找II1634

直接sort(a,a+n);输出

26.按序查找III 1635

直接sort(a,a+n);输出

27.字符转换 1641

for (int i = 0; i < s.length(); ++i)
    {
        if (s[i] >= 'A' && s[i] <= 'Z') s[i] = s[i] - ('A' - 'a');
    }

28.回文串判断 1647

注意输入有个.

s = s.substr(0, s.length() - 1);
    s1 = s;
    reverse(s.begin(), s.end());
    for (int i = 0; i < s.length(); ++i)
    {
        if (s[i] != s1[i]) { cout << "NO"; return 0; }
    }

29.数据查找1648(大水题过)

30.数据统计1649 (大水题过)

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值