B
题意:
题意:求最长等差序列的长度。
DP:摊派了我讲不明白,参考下这两篇博客吧(捂脸)
传送门1
传送门2
#include<cstdio>
#include<iostream>
#include<queue>
#include<set>
#include<algorithm>
#include <cstring>
#include <string>
using namespace std;
typedef long long ll;
const int maxn = 5e3 + 7;
int arr[maxn];
int dp[maxn][maxn];
int main()
{
std::ios::sync_with_stdio(false);
int n;
int ans = 0;
cin>>n;
for(int i = 1; i <= n; i++) cin>>arr[i];
sort(arr + 1, arr + 1 + n);
for(int i = 1; i <= n; i++){
int l = i - 1;//向左找
for(int j = i + 1; j <= n; j++){
dp[i][j] = 2;
int dis = arr[j] - arr[i];
while(l > 0 && dis > arr[i] - arr[l]) l--;
if(l > 0 && dis == arr[i] - arr[l]) dp[i][j] = dp[l][i] + 1;
ans = max(ans,dp[i][j]);
}
}
cout<<ans<<endl;
return 0;
}
F
What Goes Up Must Come Down 传送门
J
题意:
右边有n个数,从1到n, 现在把他们之间的空格去掉得到左边的字符串, 现在给出左边的字符串,求右边分隔开的数列。
先计算n的值,如果字符串长度<= 9,那么所有字符应该要独自输出,字符串长度> 9 说明存在两位的数,那么n = (lenth - 9) / 2 + 9 然后用dfs枚举所有可能序列,当前一步可以把它自己当作一个数字也可以与后一位结合成一个两位数,再找到一个之后不再继续寻找,其实我刚开始感觉dfs会爆,因为完全跑完复杂度会是 O(2n),但是一想,只需要找第一个满足条件的序列就可以,而且还有剪枝,一般是不会爆
代码
#include<cstdio>
#include<iostream>
#include<queue>
#include<set>
#include<algorithm>
#include <cstring>
#include <string>
using namespace std;
typedef long long ll;
const int maxn = 250000 + 10;
bool vis[51] , flag;
char p[100];
int arr[51],cnt,n,len;
void DFS(int i )
{
if(flag) return ;
if(i == len){
for(int i = 0; i < n; i++) printf("%d%c",arr[i], i == n - 1? '\n' : ' ');
flag =true;
}
if(i == len - 1){
int x = p[i] - '0';
if(!vis[x] && x <= n){
vis[x] = true;
arr[cnt++] = x;
DFS(i + 1);
vis[x] = false;
cnt--;
}
}
else{
int x = p[i] - '0';
if(!vis[x] && x <= n){
vis[x] = true;
arr[cnt++] = x;
DFS(i + 1);
vis[x] = false;
cnt--;
}
x = (p[i] - '0') * 10 + p[i + 1] - '0';
if(!vis[x] && x <= n){
vis[x] = true;
arr[cnt++] = x;
DFS(i + 2);
vis[x] = false;
cnt--;
}
}
}
int main()
{
//std::ios::sync_with_stdio(false);
scanf("%s",p);
len = strlen(p);
if(len < 10) for(int i = 0; i < len; i++) printf("%c%c",p[i],i == len - 1? '\n' : ' ');
else{
n = (len - 9) / 2+ 9;
DFS(0);
}
return 0;
}