蓝桥补题 2024-4-9

本文讨论了几种编程代码中出现的错误,涉及字符串处理、数组操作、数据结构如优先队列的使用,以及动态规划在最短路径问题中的应用。作者分享了错误的原因,如理解偏差和优化方法选择不当,强调了学习和理解算法的重要性。
摘要由CSDN通过智能技术生成

子串分值
错误理由:哈哈哈,错得很尴尬。先用暴力写了一发,后来发现可以用字母的位置来写,复杂度会小一点,但是推导样例的时候没有想到乘法的情况。哈哈哈哈哈,***。

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=1e3+100;
const int M=3000;
#define int long long
typedef long long ll;
typedef pair<ll,ll> PLL;

string str;
priority_queue<ll,vector<ll>,greater<ll>> q[30];
set<ll> save;

signed main (void)
{
//    ios::sync_with_stdio(false);
//    cin.tie(0);
    cin>>str;
    ll len=str.size();
    str=" "+str;
    ll ans=0;
    for(int i=1;i<=len;i++)
    {
        save.insert(str[i]-'a');
        q[str[i]-'a'].push(i);
    }
    for(auto T_T:save)
    {
        ans+=q[T_T].size();
        ll first=q[T_T].top();
        q[T_T].pop();
        ans+=first-1;
        ll last_add=first-1;
        while(q[T_T].size())
        {
            ll next=q[T_T].top();
            q[T_T].pop();
            ans+=(next-first-1)*2;
            ans+=last_add*(next-first-1);
            last_add=next-first-1;
//            cout<<last_add<<" ha "<<endl;
            first=next;
        }
//        cout<<last_add<<" ha "<<endl;
        ans+=(len-first)*last_add;
        ans+=len-first;
//        cout<<ans<<endl;
    }
    cout<<ans<<endl;
    return 0;
}

整数拼接
错误理由:哈哈哈,错得更尴尬了。最开始直接把a[i]取模了,最后前面数字乘上十的倍数那里就算错了。***。

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=1e5+100;
const int M=3000;
#define int long long
typedef long long ll;
typedef pair<ll,ll> PLL;

ll n,m;
ll a[N];
map<ll,map<ll,ll>> q;
// 将每一个数字作为右边瞧一瞧 看看有没有余数相同的
ll ans;
ll ten[15];

signed main (void)
{
//    ios::sync_with_stdio(false);
//    cin.tie(0);
    cin>>n>>m;
    ten[0]=1;
    for(int i=1;i<=10;i++)
        ten[i]=(ten[i-1]*10)%m;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        for(int j=1;j<=10;j++)
        {
            q[j][(a[i]*ten[j])%m]++;
        }
    }

    for(int i=1;i<=n;i++)
    {
        ll len= to_string(a[i]).size();
        ans+=q[len][(m-(a[i]%m))%m];
        if(((a[i]%m)*ten[len])%m==(m-(a[i])%m)%m)
            ans--;
    }
    cout<<ans<<endl;
    return 0;
}

画中漂流
错误理由:首先最开始题意理解没错,一秒钟就是可以消耗一点体力或者不消耗,那么要想最后体力不剩余,m<=t,但是题目并没有保证,我慌了。于是开始编造每一秒钟可以消耗不止一点体力。猜测是dp,但是没有想出来,就dfs写了一发… 哈哈哈,愚蠢的人类

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
#define int long long
const int P=131;
const int N=3100;
const int MOD=1e9+7;

// 每秒只能够消耗一点体力 或者不消耗体力....
// 又读错题意了
// 当时是想不通 那么既然一秒只能够消耗一点体力 那么体力值m一定是小于等于t才是有解的咯

ll d,t,m;
ll f[N][N];
// 在第i秒使用j点体力的方案数是多少

signed main (void)
{
    cin>>d>>t>>m;
    f[0][0]=1;
    for(int i=1;i<=t;i++)
    {
        for(int j=min(i,m);j>=0;j--)
        {
            // i-j是不使用体力掉下去的情况
            // j是上升的情况
            // 如果掉下去的减去上升的大于等于的话 那么就是掉下悬崖了
            if((i-j)-j>=d)
                break;// 那么此时此刻的方案数就是为零的
            // 如果能使用体力的话
            if(j)
                f[i][j]+=f[i-1][j-1];
            // 如果能够往下掉的话
            if((i-1-j)-j<d-1)
                f[i][j]+=f[i-1][j];
            f[i][j]%=MOD;
        }
    }
    cout<<f[t][m]<<endl;
    return 0;
}

最优包含
错误理由:数组开打了,MLE… 耻辱。虽然初始化的时候也错了,只初始化了f[0][0]的情况… 哈哈哈

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=1e3+100;
const int M=3000;
#define int long long
typedef long long ll;
typedef pair<ll,ll> PLL;
const int MOD=1000000007;

string str1,str2;
ll f[N][N];// 现在在第i个字符 已经有j个字符相等 需要的最小操作是多少




signed main (void)
{
//    ios::sync_with_stdio(false);
//    cin.tie(0);
    memset(f,0x3f,sizeof f);
    cin>>str1>>str2;
    ll len1=str1.size();
    ll len2=str2.size();
    str1=" "+str1,str2=" "+str2;
    for(int i=0;i<=len1;i++)
        f[i][0]=0;
    for(int i=1;i<=len1;i++)
    {
        for(int j=i;j>=1;j--)
        {
            f[i][j]=f[i-1][j];
            if(str1[i]==str2[j])
                f[i][j]=min(f[i][j],f[i-1][j-1]);
            else
                f[i][j]=min(f[i][j],f[i-1][j-1]+1);
        }
    }
    cout<<f[len1][len2]<<endl;
    return 0;
}

网络分析
错误理由:不是很懂优化的方法,就纯暴力写了。赛后听说是启发式合并,"装模做样"地写了一发,竟然过了,哈哈哈哈,还是得多学点算法。

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=1e4+100;
//#define int long long
typedef int ll;
typedef pair<ll,ll> PLL;
const int MOD=1000000007;

ll n,m;
vector<ll> save[N];
ll ans[N];
ll f[N];


ll find(ll x)
{
    if(x==f[x])
        return x;
    return f[x]=find(f[x]);
}



signed main (void)
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        f[i]=i,save[i].push_back(i);
    for(int i=1;i<=m;i++)
    {
        ll x,y,z;   cin>>x>>y>>z;
        if(x==1) {
            if(find(y)== find(z))
                continue;
            if(save[find(y)].size()<save[find(z)].size())
            {
                for(auto T_T:save[find(z)])
                    save[find(y)].push_back(T_T);
                f[find(z)]= find(y);
            }
            else
            {
                for(auto T_T:save[find(y)])
                    save[find(z)].push_back(T_T);
                f[find(y)]= find(z);
            }
        }
        else {
            for(auto T_T:save[find(y)])
                ans[T_T]+=z;
//            cout<<endl;
        }
    }
    for(int i=1;i<=n;i++)
        cout<<ans[i]<<" ";
    return 0;
}

限高杆
错误的理由:题意理解错了,以为只是恢复一条边,结果“两段道路”,哈哈哈哈。暴力写了一发。正解是分层图最短路,去好好学一学。

#include <iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=1e5+100;
#define int long long
typedef long long ll;
typedef pair<ll,ll> PLL;

struct Point{
    ll x,y,z;
};

ll n,m;
vector<PLL> Edge[N];
vector<Point> q;
ll dist[N];
bool Vis[N];


void dijkstra(){
    memset(dist,0x3f,sizeof dist);
    memset(Vis, false,sizeof Vis);
    dist[0]=0;
    dist[0+n]=0;
    dist[0+2*n]=0;
    priority_queue<PLL,vector<PLL>,greater<PLL>> q;
    q.push({0,0});
    q.push({0,0+n});
    q.push({0,0+n*2});
    while(q.size())
    {
        PLL T_T=q.top();
        q.pop();
        if(Vis[T_T.second])
            continue;
        Vis[T_T.second]=true;
        for(PLL j:Edge[T_T.second])
        {
            if(Vis[j.first])
                continue;
            if(dist[j.first]>T_T.first+j.second)
                dist[j.first]=T_T.first+j.second,q.push({dist[j.first],j.first});
        }
    }
}


signed main (void)
{
//    ios::sync_with_stdio(false);
//    cin.tie(0);
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        ll x,y,z;  cin>>x>>y>>z;
        x--,y--;
        ll k;  cin>>k;
        // 建一个两层的图
        if(k==1){
            Edge[y].push_back({x+n,z});
            Edge[y+n].push_back({x+n*2,z});
            Edge[x].push_back({y+n,z});
            Edge[x+n].push_back({y+n*2,z});
        }
        else{
            Edge[y].push_back({x,z}), Edge[x].push_back({y,z});
            Edge[y+n].push_back({x+n ,z}), Edge[x+n].push_back({y+n,z});
            Edge[y+2*n].push_back({x+n*2,z}), Edge[x+2*n].push_back({y+2*n,z});
        }
    }
    dijkstra();
    cout<<dist[n-1]-dist[n-1+2*n]<<endl;
    return 0;
}

分层图最短路例题二

#include <iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=5e5+100;
#define int long long
typedef long long ll;
typedef pair<ll,ll> PLL;



ll n,m,k;
ll st,ed;
vector<PLL> Edge[N];
ll dist[N];
bool Vis[N];
ll ans=1e18;

void dijkstra(){
    memset(dist,0x3f,sizeof dist);
    memset(Vis, false,sizeof Vis);
    priority_queue<PLL,vector<PLL>,greater<PLL>> q;
    for(int i=0;i<=k;i++)
    {
        dist[st+i*n]=0;
        q.push({0,st+i*n});
    }

    while(q.size())
    {
        PLL T_T=q.top();
        q.pop();
        if(Vis[T_T.second])
            continue;
        Vis[T_T.second]=true;
        for(PLL j:Edge[T_T.second])
        {
            if(Vis[j.first])
                continue;
            if(dist[j.first]>T_T.first+j.second)
                dist[j.first]=T_T.first+j.second,q.push({dist[j.first],j.first});
        }
    }
    for(int i=0;i<=k;i++)
        ans=min(ans,dist[ed+i*n]);
}


signed main (void)
{
//    ios::sync_with_stdio(false);
//    cin.tie(0);
    cin>>n>>m>>k;
    cin>>st>>ed;
    for(int i=1;i<=m;i++)
    {
        ll x,y,z;  cin>>x>>y>>z;
        // 建一个k层的图
        for(int j=0;j<=k;j++)
        {
            // 同一层 还有向下传递的
            Edge[y+n*j].push_back({x+n*j,z});
            Edge[x+n*j].push_back({y+n*j,z});
            if(j){
//                cout<<"ahah\n";
                Edge[y+n*(j-1)].push_back({x+n*j,0});
                Edge[x+n*(j-1)].push_back({y+n*j,0});
            }

        }
    }
    dijkstra();
    cout<<ans<<endl;
    return 0;
}

分层图例题二

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N = 510000,INF = 0x3f3f3f3f;	
typedef pair<int,int> PII;

int e[N],ne[N],w[N],h[N],idx;
int n,m,s,t,dis[N];
bool vis[N];
priority_queue<PII,vector<PII>,greater<PII> > q;	

void add(int a,int b,int c)	
{
	e[idx] = b;
	ne[idx] = h[a];
	w[idx] = c;
	h[a] = idx++;
}

void dijkstra(int s)	
{
	memset(dis,INF,sizeof dis);
	dis[s] = 0;
	q.push({0,s});

	while(!q.empty())
	{
		int u = q.top().second;
		q.pop();
		if(vis[u])
			continue;
		vis[u] = 1;
		for(int i = h[u]; ~i;i = ne[i])
		{
			int v = e[i];
			if(dis[v] > dis[u]+w[i])
			{
				dis[v] = dis[u]+w[i];
				q.push({dis[v],v});
			}
		}
	}
}

int main()
{
	int price,ad,num,pre,cur;
	cin >> n >> m >> s >> t;
	memset(h,-1,sizeof h);
	for(int i = 1;i <= m;i++)
	{
		cin >> price >> ad >> num;
		for(int j = 0;j < num;j++)
		{
			cin >> cur;
			if(j)
			{
				add((i-1)*n+pre,(i-1)*n+cur,ad);	
				add((i-1)*n+cur,(i-1)*n+pre,ad);	
			}
			add((i-1)*n+cur,n*m+cur,0);	
			add(n*m+cur,(i-1)*n+cur,price);	
			pre = cur;
		}
	}

	dijkstra(n*m+s);	
	if(dis[n*m+t] == INF)	
		cout << -1 << endl;
	else
		cout << dis[n*m+t] << endl;

	return 0;
}

待补的题

皮亚诺曲线距离
没写的理由:这图也…太抽象了吧

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值