补题(2022东北四省 选拔赛)

本文探讨了四个编程竞赛题目,涉及字符串处理、最短路径算法和数组优化策略。第一题通过规律找到将所有价值聚集的最小步数;第二题使用Floyd算法求解字符转换的最短路径;第三题是关于字符串排列的计数问题,利用动态规划求解;第四题通过贪心策略优化数组以获得最大序列和。这些题目展示了在算法设计中的思考和应用。
摘要由CSDN通过智能技术生成

题目链接:​​​​​​Board Moves - CodeForces 1353C - Virtual Judge (vjudge.net)

题解来源:(34条消息) Codeforces 1353 C. Board Moves(规律)_Huffman_Tree_的博客-CSDN博客

思维 找规律

题意:给定N*N的正方形,每个位置上有一个价值,你可以通过走八个偏移量,每次只能走一步,求出让所有价值附加在一点上的最小步数

思路:对于所有价值我们可以全部集合到最中间的那个点上。

#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
   int t;
   cin>>t;
   
   while(t--)
   {
       int x;
	   cin>>x;
	   int k=(x+1)/2-1;
	   int m=0,sum=0;
	   
	   for(int i=k;i>=1;i--)
	   {
	   	    m=x*4-4;
	   	    sum+=m*i;
	   	    x-=2;
	   }   
	   
	   cout<<sum<<endl;
	   
   }

	return 0;
}

题目链接:String Problem - CodeForces 33B - Virtual Judge (vjudge.net)s

题解来源:(34条消息) Codeforces 33B. String Problem(Floyd最短路)_baodream的博客-CSDN博客

Floyd  

题意: 给定两个字符串,和n个操作,每次可以让一个字符变为另外一个字符且消耗价值w,问可不可以让这两个字符串变为相同的另外一个字符串,求消耗的最小价值和变成的字符串

思路:floyd求出n个字符变换的最小价值,再通过枚举给定字符串长度的大小来一次次在已经确定好的最短路字符方案里找可行方案并更新最小距离。

#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=1e5+10,M=1,inf=0x3f3f3f3f;
int g[30][30];
char a[N],b[N],c[N];
int t;

void floyd()
{
	for(int k=0;k<=25;k++)
	{
		for(int i=0;i<=25;i++)
		{
			for(int j=0;j<=25;j++)
			{
				g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
			}
		}
	}
}


int main()
{
    cin>>a>>b>>t;
    
    for(int i=0;i<30;i++)
    {
    	for(int j=0;j<30;j++)
    	{
    		if(i==j) g[i][j]=0;
    		else g[i][j]=inf;
		}
	}
    
    
    for(int i=0;i<t;i++)
    {
    	char x,y;
    	int w;
    	
    	cin>>x>>y>>w;
    	
    	g[x-'a'][y-'a']=min(g[x-'a'][y-'a'],w);
    	
	}
    
    floyd();
    
    bool flag=false;
    
    int ans=0;
    
    if(strlen(a)!=strlen(b))
    {
    	cout<<-1<<endl;
    	return 0;
	}

    int len=strlen(a);
    
    for(int i=0;i<len;i++)
    {
    	int minn=inf;
    	
    	int t1=a[i]-'a';
    	int t2=b[i]-'a';
    	
    	for(int j=0;j<=25;j++)
    	{
    		int x1=g[t1][j];
    		int x2=g[t2][j];
    		
    		if(x1!=inf&&x2!=inf&&minn>x1+x2)
    		{
    			minn=x1+x2;
				c[i]='a'+j; 
			}
    		
		}
		
		if(minn==inf)
		{
			flag=true;
			break;
		}
		
		ans+=minn;
    	
	}

    if(flag) 
    {
    	cout<<-1<<endl;
    	return 0;
	}
	
	//c[len]='\0';
	cout<<ans<<endl;
	cout<<c<<endl;


	return 0;
}

题目链接:chokudai - AtCoder abc211_c - Virtual Judge (vjudge.net) 

题解链接: (34条消息) AtCoder Beginner Contest 211 C - chokudai_CCSU_梅子酒的博客-CSDN博客

dp

题意:给定一个字符串a="chokudai",输入一个字符串s,问有多少种方案可以让唯一顺序读出这个字符串,求所给方案

思路:遍历字符串s,每次让字符串中的字符与a中字符串比较

dp[j][i]记录的是字符串s前1~j位子序列的方案数。

在我们遍历字符串S的时候需要对每个字符匹配其是否为a中的一种,若匹配成功则状态转移方程为:dp[j][i]=dp[j-1][i-1]+dp[j][i-1]

含义为dp[j][i]=S串中之前一位匹配成功的a[1~j]的方案数(dp[j][i-1])+之前一位匹配成功的a[1~j-1]的方案数和本次这一个j字符凑成新的a[1~j]方案(dp[j-1][i-1])

同时注意需要特判的是当我们匹配的字符是第一个时即“c”字符因为之前没有字符串给其加上权值了即dp[j-1][i-1]是无效的方程需要写成dp[j][i]=dp[j][i-1]+1
二、匹配不成功就很简单了,只需要加上S串上一位的a[1~j]的值dp[j][i]=dp[j][i-1]
最后答案就是dp[8][len]了,注意要记得对1e9+7取模

string a="0chokudai"; string s; cin>>s; s='0'+s;//防止dp状态转移时越界在0位置增加一个字符防止转态转移时数组越界

#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=1e5+10,M=1,inf=0x3f3f3f3f,mod=1e9+7;
string s;
string a="0chokudai";
int dp[10][N]; 

int main()
{
    cin>>s;
    
    s="0"+s;
    
    for(int i=1;i<=s.size();i++)
    {
    	for(int j=1;j<=8;j++)
		{
			if(s[i]==a[j])
			{
				if(j==1) dp[j][i]=dp[j][i-1]+1;
				else dp[j][i]=dp[j-1][i-1]+dp[j][i-1];
			}
			else
			{
				dp[j][i]=dp[j][i-1];
			}
			
			dp[j][i]%=mod; 
		} 
	}
	
	cout<<dp[8][s.size()]<<endl;

	return 0;
}

Two Arrays And Swaps - CodeForces 1353B - Virtual Judge (vjudge.net)

 题意:给定两个数组a和b,允许交换k次,问a最大序列和

贪心  排序

当时没时间了,哎,其实很简单

#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=1e5+10,M=1,inf=0x3f3f3f3f,mod=1e9+7;
int t;
int a[N],b[N];

int main()
{
	cin>>t;
    while(t--)
    {
    	int n,k;
    	cin>>n>>k;
		
		for(int i=0;i<n;i++) cin>>a[i];
		
		for(int i=0;i<n;i++) cin>>b[i];
		
		sort(b,b+n,greater<int>());
		sort(a,a+n);
		
		for(int i=0;i<k;i++)
		{
			if(b[i]>a[i])
			swap(a[i],b[i]);
		}
		
		int sum=0;
		
		for(int i=0;i<n;i++) sum+=a[i];
		
		cout<<sum<<endl;
		
	}//
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值