Codeforces Round #290 (Div. 1) 解题报告(A B)

本文探讨了如何通过改进算法和数据结构实现高效的数据处理。包括排序算法优化、动态规划应用、哈希算法效率提升、贪心算法策略、深度优先搜索优化等。同时,文章还涉及了数据结构如二叉树、队列、栈、数组、链表、B树、散列表的应用与优化。旨在提高程序执行速度与资源利用效率。

A. Fox And Names


        有一些仅包含小写字母的字符串,问能不能给26个字母定义一个顺序,使得那些串是按字典序排列的。

        把每个字母作为图的一个顶点,对每两个串,找到它们第一个相异的字母,建边,跑拓扑排序。注意处理串前缀相同,但是长度不同的情况,长的串字典序靠后。

#include <iostream>  
#include <stdio.h>  
#include <string>  
#include <map>  
#include <vector>  
#include <stack>  
#include <queue>  
#include <string.h>  
#include <algorithm>  
#include <math.h>  
  
using namespace std;  

string names[110];
bool mat[30][30];
int len[110];
bool vis[30];
stack<int> ans;

void dfs(int u){
	
	vis[u]=1;
	for(int i=0;i<26;i++){
		if(mat[u][i]){
			if(!vis[i])dfs(i);
		}
	}
	ans.push(u);
}

int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>names[i];
		len[i]=names[i].size();
	}
	
	bool ok=1;
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			int sz=min(len[i],len[j]);
			int k=0;
			for(k=0;k<sz;k++){
				if(names[i][k]!=names[j][k])break;
			}
			if(k!=sz){
				
				mat[names[i][k]-'a'][names[j][k]-'a']=1;
			}else{
				if(len[i]>len[j])ok=0;
			}
			
		}
	}
	
	for(int k=0;k<26;k++){
		for(int i=0;i<26;i++){
			for(int j=0;j<26;j++){
				if(mat[i][k]&&mat[k][j]){
					mat[i][j]=1;
				}
			}
		}
	}
	
	for(int i=0;i<26;i++){
		for(int j=0;j<26;j++){
			if(mat[i][j]&&mat[j][i]){
				ok=0;
			}
		}
	}
	
	if(ok){
		for(int i=0;i<26;i++){
			if(!vis[i]){
				dfs(i);
			}
		}
		while(!ans.empty()){
			char ch=ans.top()+'a';
			ans.pop();
			cout<<ch;
		}
	}else{
		cout<<"Impossible"<<endl;
	}
	return 0;
}

B. Fox And Jumping


        有一些卡片,卡片i长度为li,花费ci,买了以后就可以无限用。你需要用尽可能少的钱,使得那些li能互相加减凑出所有自然数。

        分析一下。。凑出所有自然数就是要凑出1,凑出1的条件是它们的最大公约数为1。那么我们就可以用dp来解决,dp(i)表示凑i的最小花费,对每张卡片去更新dp。因为花费的取值范围比较大,我开了两个map来解决,当然也可以哈希。

#include <iostream>  
#include <stdio.h>  
#include <string>  
#include <map>  
#include <vector>  
#include <stack>  
#include <queue>  
#include <string.h>  
#include <algorithm>  
#include <math.h>  
  
using namespace std;  

int l[310];
int c[310];

map<int,int> mp;

int gcd(int a, int b){ return a == 0 ? b : gcd(b % a, a); } 

int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>l[i];
	}
	for(int i=1;i<=n;i++){
		cin>>c[i];
	}
	
	mp[0]=0;
	for(int i=1;i<=n;i++){
		map<int,int> tmp;
		map<int,int>::iterator it=mp.begin();
		for(;it!=mp.end();it++){
			int cmp=mp[it->first]+c[i];
			int pos=gcd(it->first,l[i]);
			if(mp.count(pos)==0||mp[pos]>cmp){
				if(tmp.count(pos)&&tmp[pos]<cmp)continue;
				tmp[pos]=cmp;
			}
		}
		//
		
		it=tmp.begin();
		for(;it!=tmp.end();it++){
			mp[it->first]=it->second;
		}
	}
	
	if(mp[1]!=0){
		cout<<mp[1]<<endl;
	}else{
		cout<<"-1"<<endl;
	}
	return 0;
}





评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值