HAUT 1262 魔法宝石 暴力思想,多种解决方案

本文介绍了一个关于魔法宝石合成的问题,通过使用SPFA算法解决宝石合成过程中如何以最小的魔力值合成目标宝石。同时提供了两种解决方案,一种是利用SPFA算法进行优化,另一种则是采用暴力迭代的方法。

魔法宝石

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 254    Accepted Submission(s): 85


Problem Description
小s想要创造n种魔法宝石。小s可以用ai的魔力值创造一棵第i种魔法宝石,或是使用两个宝石合成另一种宝石(不消耗魔力值)。请你帮小s算出合成某种宝石的所需的最小花费。
 

Input
第一行为数据组数T(1≤T≤3)。
对于每组数据,首先一行为n,m(1≤n,m≤10^5)。分别表示魔法宝石种类数和合成魔法的数量。
之后一行n个数表示a1an。(1≤ai≤10^9)。ai表示合成第i种宝石所需的魔力值。
之后m行,每行三个数a,b,c(1≤a,b,c≤n),表示一个第a种宝石和第b种宝石,可以合成一个第c种宝石。
 

Output
每组数据输出一行n个数,其中第i个数表示合成第i种宝石的魔力值最小花费。
 

Sample Input
1 3 1 1 1 10 1 2 3
 

Sample Output
1 1 2
 

有n种宝石,让伟大的魔法师去合成,耗费最少的魔法值,题意表述的挺清晰的,不过,不保证没有圈的存在,比如a+b=c;a+c=b;b+c=a; 这样就有点ggl了,咋办。。。。

第一次看到这道题是17年山东省浪潮杯热身赛,当时第一次去参加省赛,激动,这个题没做出来,后来想了想热身赛。没事哒,不过后来又在杭电的一个比赛上看到了,确实该弄弄了,不能一直没进步。

思路,用spfa,记录下来每一个改变过的点,然后去搜索,搜索时找到这个点改变的起点(如果a+b=c),就找a,把所有从a开始的点都更新一遍,那些变动的点再次进入队列,从重复下去一定可以走到所有点的稳定状态----最小状态。

spfa


#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>

using namespace std;
const int maxn=1e5+5;
int t;
int n,m,len;
int mi[maxn];
int first[maxn];
bool ex[maxn];
queue <int> Q;
struct node{
	int v1,v2,nxt;
}nn[maxn*2];

void spfa(){
	
	while(!Q.empty()){
		int st=Q.front();
		Q.pop();
		ex[st]=false;
		for(int i=first[st];i!=-1;i=nn[i].nxt){
			int v1=nn[i].v1,v2=nn[i].v2;
			if(mi[v2] > mi[v1]+mi[st]){
				mi[v2] = mi[v1]+mi[st];
				if(!ex[v2]){
					Q.push(v2);
					ex[v2]=true;
				}
			}
		}
	}
}

void add_pi(int u,int v1,int v2){
	
	nn[len].v1=v1;
	nn[len].v2=v2;
	nn[len].nxt=first[u];
	first[u]=len++;
}
int main()
{
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n,&m);
		memset(first,-1,sizeof(first));
		memset(ex,false,sizeof(ex));
		while(!Q.empty())
			Q.pop();
		for(int i=1;i<=n;i++){
			scanf("%d",mi+i);
		}
		int a,b,c;
		len=0;
		for(int i=1;i<=m;i++){
			scanf("%d%d%d",&a,&b,&c);
			add_pi(a,b,c);
			add_pi(b,a,c);
			if( mi[c] > mi[a] + mi[b] ){
				mi[c] = mi[a] + mi[b];
				if(!ex[c]){
					Q.push(c);
					ex[c]=true;	
				}
				
			}
		}
		spfa();
		printf("%d",mi[1]);
		for(int i=2;i<=n;i++){
			printf(" %d",mi[i]);
		}
		printf("\n");
	}	
	
	return 0;
}

既然只要把所有点稳定状态找到就可以,那么 直接暴力就可以哒

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <queue>
#include <algorithm>

using namespace std;
const int MAXN=1e5+5;
int t;
int n,m;
int p[MAXN],mi[MAXN];
int a,b,c;
struct node{
    int v1,v2,nxt;
}nn[MAXN];

int main()
{
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",p+i);
            mi[i]=p[i];
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&a,&b,&c); 
            nn[i].v1=a;
            nn[i].v2=b;
            nn[i].nxt=c;
        }
        int flag=0;
        while(1){
            for(int i=1;i<=m;i++){
                int sum=mi[nn[i].v1]+mi[nn[i].v2];
                
                if(sum < mi[nn[i].nxt]){
                	mi[nn[i].nxt]=sum;	
					flag=1;
				}
            } 
            if(!flag)
            	break ;
            flag=0;
        }
        printf("%d",mi[1]);
        for(int i=2;i<=n;i++){
            printf(" %d",mi[i]);
        }
        printf("\n");
    }    
    
    return 0;
}


暴力50次也可以过,估计比赛的时候很多人都是暴力过的吧

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <queue>
#include <algorithm>

using namespace std;
const int MAXN=1e5+5;
int t;
int n,m;
int p[MAXN],mi[MAXN];
int a,b,c;
struct node{
    int v1,v2,nxt;
}nn[MAXN];

int main()
{
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",p+i);
            mi[i]=p[i];
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&a,&b,&c); 
            nn[i].v1=a;
            nn[i].v2=b;
            nn[i].nxt=c;
        }
        int o=50;
        while(o--){
            for(int i=1;i<=m;i++){
                int sum=mi[nn[i].v1]+mi[nn[i].v2];
                
                if(sum < mi[nn[i].nxt])
                    mi[nn[i].nxt]=sum;
            } 
        }
        printf("%d",mi[1]);
        for(int i=2;i<=n;i++){
            printf(" %d",mi[i]);
        }
        printf("\n");
    }    
    
    return 0;
}




(1)普通用户端(全平台) 音乐播放核心体验: 个性化首页:基于 “听歌历史 + 收藏偏好” 展示 “推荐歌单(每日 30 首)、新歌速递、相似曲风推荐”,支持按 “场景(通勤 / 学习 / 运动)” 切换推荐维度。 播放页功能:支持 “无损音质切换、倍速播放(0.5x-2.0x)、定时关闭、歌词逐句滚动”,提供 “沉浸式全屏模式”(隐藏冗余控件,突出歌词与专辑封面)。 多端同步:自动同步 “播放进度、收藏列表、歌单” 至所有登录设备(如手机暂停后,电脑端打开可继续播放)。 音乐发现与管理: 智能搜索:支持 “歌曲名 / 歌手 / 歌词片段” 搜索,提供 “模糊匹配(如输入‘晴天’联想‘周杰伦 - 晴天’)、热门搜索词推荐”,结果按 “热度 / 匹配度” 排序。 歌单管理:创建 “公开 / 私有 / 加密” 歌单,支持 “批量添加歌曲、拖拽排序、一键分享到社交平台”,系统自动生成 “歌单封面(基于歌曲风格配色)”。 音乐分类浏览:按 “曲风(流行 / 摇滚 / 古典)、语言(国语 / 英语 / 日语)、年代(80 后经典 / 2023 新歌)” 分层浏览,每个分类页展示 “TOP50 榜单”。 社交互动功能: 动态广场:查看 “关注的用户 / 音乐人发布的动态(如‘分享新歌感受’)、好友正在听的歌曲”,支持 “点赞 / 评论 / 转发”,可直接点击动态中的歌曲播放。 听歌排行:个人页展示 “本周听歌 TOP10、累听歌时长”,平台定期生成 “全球 / 好友榜”(如 “好友中你本周听歌时长排名第 3”)。 音乐圈:加入 “特定曲风圈子(如‘古典音乐爱好者’)”,参与 “话题讨论(如‘你心中最经典的钢琴曲’)、线上歌单共创”。 (2)音乐人端(创作者中心) 作品管理: 音乐上传:支持 “无损音频(FLAC/WAV)+ 歌词文件(LRC)+ 专辑封面” 上传,填写 “歌曲信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值