第0届ACM算法竞赛热身赛 题解

A题(Hello World!)

题目链接:http://116.62.114.238/problem/1037

#include<bits/stdc++.h>
using namespace std;
int main()
{
	
	cout << "Hello World!" << endl;
	return 0;
}

B题(多源最短路听说过吗)

题目链接:http://116.62.114.238/problem/1034
Floyd弗洛伊德算法
求任意两个点之间的最短路径,啊哈算法P149写的很详细。。。

#include<bits/stdc++.h>
using namespace std;
int a[600][600];

int main()
{
	int n;
	cin >> n;
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= n; j++) {
			int x;
			cin >> x;
			if(x != 0) {
				a[i][j] = x;
			} 
			else
				a[i][j] = 0;
		}
	}
	for(int k = 1; k <= n; k++) {
		for(int i = 1; i <= n; i++) {
			for(int j = 1; j <= n; j++) {
				if(a[i][j] > a[i][k] + a[k][j]) 
					a[i][j] = a[i][k] + a[k][j];
			}
		}
	} 
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= n; j++) {
			cout << a[i][j] << " "; 
		}
		cout << endl;
	}
	return 0;
}

C题(阶乘)

题目链接:http://116.62.114.238/problem/1036

#include<bits/stdc++.h>
using namespace std;
int a[1000];
int main()
{
	int n;
	cin >> n;
	a[1] = 1;
	for(int i = 2; i <= n; i++) {
		a[i] = a[i-1] * i;
	}
	cout << a[n] << endl;
	return 0;
}

D题

题目链接:http://116.62.114.238/problem/1035
https://www.lydsy.com/JudgeOnline/problem.php?id=2423
第一问(求长度):可以参考白皮书P57
让你求最长公共子序列(LCS)的长度,一个基础的DP。定义一个数组dp[i][j] ,表示从第一个字符串第1位到第i位和第二个字符串第1位到第j位中的最长公共子序列的长度(可以不连续)。使用滚动数组,否则会爆内存。。
①如果s[i] == t[j],那么dp[i][j] = dp[i-1][j-1] + 1;
②如果s[i] != t[j], 那么dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
第二问(求最长公共子序列个数): 就比较麻烦了
定义g[i][j]为第一个字符串第1位到第i位和第二个字符串第1位到第j位中的最长公共子序列的个数
(1)如果a[i] == b[j]
此时公共子序列的长度应该加1(dp[i][j]=dp[i-1][j-1]+1),那么它的最长公共子序列的个数应该最少与他上一次相等即g[i][j] = g[i-1][j-1]。
这时你就需要判断
①是否dp[i][j] == dp[i-1][j],例如ABDD和ACD,i为4,j为3。这时dp[i][j] = dp[i-1][j], 那么就又会多出g[i-1][j]次。即g[i][j] += g[i-1][j];
②是否dp[i][j] = dp[i][j-1],例如ABCDE和BDEE,i为5,j为4。这时dp[i][j] = dp[i][j-1],那么就又会多出g[i][j-1]。即g[i][j] += g[i][j-1];
(2)如果a[i] != b[j]
①此时先判断是否dp[i][j] == dp[i-1][j], 那么g[i][j] += g[i-1][j];
②此时判断是否dp[i][j] ==dp[i][j-1],即g[i][j] += g[i][j-1]
③此时判断是否dp[i][j] == dp[i-1][j-1],如果相等,就相当与多加了一个①,那么这时需要剪掉一个①,即g[i][j] -= g[i-1][j].

注意使用滚动数组。

#include <bits/stdc++.h>
using namespace std;
const long long mod=1e8;

char a[5010],b[5010];
int  dp[2][5010],g[2][5010];
int main()
{
    scanf("%s%s",a+1,b+1);
    int l1=strlen(a+1)-1,l2=strlen(b+1)-1;
    for(int i=0;i<=l2;i++)
       g[0][i]=1;
    g[1][0]=1;
    for(int i=1;i<=l1;i++){
    	int nw=i&1,pr=nw^1;   
    	for(int j=1;j<=l2;j++){
    		if(a[i]==b[j])
    		{
    			dp[nw][j]=dp[pr][j-1]+1;
	    		g[nw][j]=g[pr][j-1];
	    		if(dp[nw][j]==dp[nw][j-1])
	    		  g[nw][j]=(g[nw][j]+g[nw][j-1])%mod;
	    		if(dp[nw][j]==dp[pr][j])
	    		  g[nw][j]=(g[nw][j]+g[pr][j])%mod;
    		}
    		else
    		{
    			dp[nw][j]=max(dp[pr][j],dp[nw][j-1]);
    			g[nw][j]=0;
    			if(dp[nw][j]==dp[nw][j-1])
	    		  g[nw][j]=(g[nw][j]+g[nw][j-1])%mod;
	    		if(dp[nw][j]==dp[pr][j])
	    		  g[nw][j]=(g[nw][j]+g[pr][j])%mod;
	    		if(dp[nw][j]==dp[pr][j-1])
	    		  g[nw][j]=(g[nw][j]-g[pr][j-1])%mod;
    		}
    	}	
    }
    cout<<dp[l1&1][l2]%mod<<endl;
    cout<<(g[l1&1][l2]+mod)%mod<<endl;   
	return 0;
}

E题(cycle! cycle!)

题目链接:http://116.62.114.238/problem/1033

#include<bits/stdc++.h>
using namespace std;
int a[1000];
int main()
{
	int n;
	cin >> n;
	int sum = 0;
	for(int i = 0; i < n; i++) {
		cin >> a[i];
		sum += a[i];
	}
	cout << sum << endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Sclong0218/article/details/83929135