前言

一共5道题,都是原题,2道英文题是算法课的作业题,以为不会考,结果考了,勉强做了4个,最后一个忘了转移方程了,想写个暴力的解法,结果没写完。本来以为会出个回溯题的,但是一个也没出,白练了一堆。整体就是dp+贪心+dp+模拟+hash,比较一般,对题目有点失望。

最长公共子序列

两个签到题之一

题目描述

一个字符串A的子串被定义成从A中顺次选出若干个字符构成的串。如A=“cdaad” ,顺次选1,3,5个字符就构成子串” cad” ,现给定两个字符串,求它们的最长共公子串。

输入

第一行两个字符串用空格分开。两个串的长度均小于2000 。

输出

最长子串的长度。

样例输入

abccd aecd

样例输出

3

代码

#include<bits/stdc++.h>
using namespace std;
const int N=2010;
char a[N],b[N];
int dp[N][N];
int main(){
cin>>a+1>>b+1;
int l1=strlen(a+1);
int l2=strlen(b+1);
for(int i=1;i<=l1;i++){
for(int j=1;j<=l2;j++){
if(a[i]==b[j]) dp[i][j]=dp[i-1][j-1]+1;
else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
cout<<dp[l1][l2];
return 0;
}

跳跃游戏2

另一个签到题,简单的贪心,这两题做了就能及格了

题目描述

给定一个非负整数数组,假定你的初始位置为数组第一个下标。数组中的每个元素代表你在那个位置能够跳跃的最大长度。你的目标是到达最后一个下标,并且使用最少的跳跃次数。例如:A = [2,3,1,1,4],到达最后一个下标的最少跳跃次数为 2。(先跳跃11步,从下标0到1,然后跳跃3步,到达最后一个下标。一共两次)

输入

第一行输入一个正整数n(1≤n≤100),接下来的一行,输入n个整数,表示数组A。

输出

最后输出最少的跳跃次数。

样例输入

5
3 1 1 1 1

样例输出

2

代码

#include<bits/stdc++.h>
using namespace std;
const int N=110;
int a[N];
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
int ans=0,m=0,end=0;
for(int i=0;i<n-1;i++){
if(m>=i){
m=max(m,i+a[i]);
if(i==end){
end=m;
ans++;
}
}
}
cout<<ans;
return 0;
}

Rock-Paper-Scissors Tournament

其中一个英文题,还行,只是个模拟

题目描述

Rock-Paper-Scissors is game for two players, A and B, who each choose, independently of the other, one of rock, paper, or scissors. A player chosing paper wins over a player chosing rock; a player chosing scissors wins over a player chosing paper; a player chosing rock wins over a player chosing scissors. A player chosing the same thing as the other player neither wins nor loses.
A tournament has been organized in which each of n players plays k rock-scissors-paper games with each of the other players - kn(n-1)/2 games in total. Your job is to compute the win average for each player, defined as w / (w + l) where w is the number of games won, and l is the number of games lost, by the player.

输入

Input consists of several test cases. The first line of input for each case contains 1 <= n <= 100 1 <= k <= 100 as defined above. For each game, a line follows containing p1, m1, p2, m2. 1 <= p1 <= n and 1 <= p2 <= n are distinct integers identifying two players; m1 and m2 are their respective moves (“rock”, “scissors”, or “paper”). A line containing 0 follows the last test case.

输出

Output one line each for player 1, player 2, and so on, through player n, giving the player’s win average rounded to three decimal places. If the win average is undefined, output “-“. Output an empty line between cases.

样例输入

2 4
1 rock 2 paper
1 scissors 2 paper
1 rock 2 rock
2 rock 1 scissors
2 1
1 rock 2 paper
0

样例输出

0.333
0.667

0.000
1.000

代码

#include<bits/stdc++.h>
using namespace std;
const int N=110;
int win[N],loss[N];
int main(){
int n,k;
while(cin>>n){
if(n==0) break;
cin>>k;
memset(win,0,sizeof(win));
memset(loss,0,sizeof(loss));
int t1,t2;
string s1,s2;
int m=k*n*(n-1)/2;
for(int i=0;i<m;i++){
cin>>t1>>s1>>t2>>s2;
if(s1[0]=='r'&&s2[0]=='s'||s1[0]=='s'&&s2[0]=='p'||s1[0]=='p'&&s2[0]=='r'){
win[t1]++;
loss[t2]++;
}else if(s1[0]=='s'&&s2[0]=='r'||s1[0]=='p'&&s2[0]=='s'||s1[0]=='r'&&s2[0]=='p'){
win[t2]++;
loss[t1]++;
}
}
for(int i=1;i<=n;i++){
if(win[i]==0&&loss[i]==0) cout<<"-\n";
else{
double t=1.0*win[i]/double(win[i]+loss[i]);
printf("%.3f\n",t);
}
}
cout<<endl;
}
return 0;
}

Brackets Sequence

没做出来的一个题,整个年级就一个人做出来了(汗),其实就是个区间dp,就是打印比较繁琐

题目描述

Let us define a regular brackets sequence in the following way:

  1. Empty sequence is a regular sequence.
  2. If S is a regular sequence, then (S) and [S] are both regular sequences.
  3. If A and B are regular sequences, then AB is a regular sequence.

For example, all of the following sequences of characters are regular brackets sequences:

(), [], (()), ([]), ()[], ()[()]

And all of the following character sequences are not:

(, [, ), )(, ([)], ([(]

Some sequence of characters ‘(‘, ‘)’, ‘[‘, and ‘]’ is given. You are to find the shortest possible regular brackets sequence, that contains the given character sequence as a subsequence. Here, a string a1 a2 … an is called a subsequence of the string b1 b2 … bm, if there exist such indices 1 = i1 < i2 < … < in = m, that aj = bij for all 1 <= j< = n.

输入

The input file contains at most 100 brackets (characters ‘(‘, ‘)’, ‘[‘ and ‘]’) that are situated on a single line without any other characters among them.

输出

Write to the output file a single line that contains some regular brackets sequence that has the minimal possible length and contains the given sequence as a subsequence.

样例输入

([(]

样例输出

([(]

代码

// dp[i][j] 从i到j需要添加括号的个数
// dp[i][j]=dp[i+1][j-1] match(i,j)
// dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j])

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 256;
char br[MAXN];
int dp[MAXN][MAXN], pos[MAXN][MAXN];
int len;
void print_br(int i, int j)
{
if (i > j)
return;
if (i == j)
{
if (br[i] == '(' || br[j] == ')')
printf("()");
else
printf("[]");
}
else if (pos[i][j] == -1)
{
printf("%c", br[i]);
print_br(i + 1, j - 1);
printf("%c", br[j]);
}
else
{
print_br(i, pos[i][j]);
print_br(pos[i][j] + 1, j);
}
}
bool match(int i, int j)
{
if (br[i] == '(' && br[j] == ')')
return true;
if (br[i] == '[' && br[j] == ']')
return true;
return false;
}
int main()
{
int i, j, k, mid, t;
while (gets(br) != NULL)
{
memset(dp, 0, sizeof(dp));
len = strlen(br);
for (i = 0; i < len; i++)
{
dp[i][i] = 1;
}
for (k = 1; k < len; k++)
{
for (i = 0; i + k < len; i++)
{
j = i + k;
dp[i][j] = 0x7fffffff;
if (match(i, j))
{
dp[i][j] = dp[i + 1][j - 1];
pos[i][j] = -1;
}
for (k = i; k < j; k++)
{
if (dp[i][j] > (t = dp[i][k] + dp[k + 1][j]))
{
dp[i][j] = t;
pos[i][j] = k;
}
}
}
}
print_br(0, len - 1);
printf("\n");
}
}

sort2

数据比之前大了很多到了1e6,不过数组能正常存,用sort肯定就寄了,写个类似计数排序就可以

题目描述

给你n个整数,请按从大到小的顺序输出其中前m大的数。

输入

每组测试数据有两行,第一行有两个数n,m(0<n,m<1000000),第二行包含n个都处于区间[-500000,500000]的整数,整数可能会重复出现。

输出

对每组测试数据按从大到小的顺序输出前m大的数。

样例输入

10 5
1 2 3 4 5 6 7 7 8 9

样例输出

9 8 7 7 6

代码

#include<bits/stdc++.h>
using namespace std;
const int N=1000000+10;
int a[N];
int main(){
int n,m,t;
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>t;
a[t+500000]++;
}
int ans=0;
for(int i=1000000;i>=0;i--){
if(ans==m) break;
while(a[i]!=0){
cout<<i-500000<<' ';
ans++;
a[i]--;
if(ans==m) break;
}
}
return 0;
}