A 斗牛
直接暴力求解即可
#include<iostream>
using namespace std;
const int N = 1010;
int a[5],sum;
bool flag;
int main(){
int T;
cin >> T;
while(T--){
for(int i = 0;i < 5;i++) cin >> a[i];
flag = false;
for(int i = 0;i <5; i++)
if(!flag)
for(int j = i + 1;j <5; j++)
if(!flag)
for(int k = j + 1;k < 5;k++)
if((a[i] + a[j] + a[k]) % 10 == 0)
{
flag = true;
sum = 0;
for(int q = 0;q < 5; q++)
if(q != i && q != j && q!= k)
sum += a[q];
cout << sum % 10 << endl;
break;
}
if(!flag) cout << -1 <<endl;
}
return 0;
}
B 打地鼠
此题重点是要看出最长选择方案中一定有最小值,则排序后从最小值开始遍历即可。我用的是set。也可以直接用sort函数排序。
#include<iostream>
#include<set>
#include<algorithm>
using namespace std;
const int N = 1e5 +10;
int n,d;
multiset<int> a;
int main(){
cin >> n >> d;
for(int i = 1;i <= n;i++) {
int x;
cin >> x;
a.insert(x);
}
auto x = *a.begin();
int length = 1;
while(a.lower_bound(x + d) != a.end()) { //a.lower_bound(x)的功能为输出a中大于等于x的最
小值的迭代器。若没有则输出a.end()
x = *a.lower_bound(x + d);
length ++;
}
cout <<length;
return 0;
}
C 排队打饭
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
int a[N],t[N],b[N];
int n;
int main(){
cin >> n;
for(int i = 1;i <= n;i++) cin >> a[i] >> t[i] >> b[i];
int time = a[1];
for(int i = 1;i <= n;i++){
if(a[i] + b[i] >= time){
cout << time << ' ';
time += t[i];
}
else cout << -1 << ' ';
}
return 0;
}
D 二叉搜索树
用数组存储二叉树的做法。这种做法空间复杂度过高,A不了本题。是我最开始的一种思路。
//11.51 - 12.26
#include<iostream>
using namespace std;
const int N = 1e5 +10;
int a[N],b[N]; //a数组应该开的比这个大得多,这里只是验证小数据时可以
void insert(int root,int x){ //将x插入以root节点后面
if(x > a[root]){
int r = root * 2 + 1;
if(a[r]) insert(r,x);
else {
a[r] = x;
b[x] = a[root];
}
}
else {
int l = 2 * root;
if(a[l]) insert(l,x);
else{
a[l] = x;
b[x] = a[root];
}
}
}
int main(){
int n;
cin >> n;
int x;
cin >> x;
a[1] = x;
for(int i = 2;i <= n;i++){
cin >> x;
insert(1,x);
}
for(int i = 1;i <= n;i++) cout << b[i] << ' ';
return 0;
}
数组存储二叉树的改进方法。设置两个数组l[N]与r[N]。l[i]、r[i]代表i的左孩子与右孩子。其他思路与前面类似。体现了以空间换时间的方法。
代码转自其他博客。
#include<iostream>
using namespace std;
const int N=1e5+10;
int l[N],r[N],fa[N];
int n;
int root;
void insert(int i,int root)
{
if(i<root)
{
if(!l[root])
{
l[root]=i;
fa[i]=root;
return ;
}
else
{
insert(i,l[root]);
}
}
else if(i>root)
{
if(!r[root])
{
r[root]=i;
fa[i]=root;
return ;
}
else
{
insert(i,r[root]);
}
}
}
int main()
{
cin>>n;
cin>>root;
fa[root]=0;
for(int i=1;i<n;i++)
{
int t;
cin>>t;
insert(t,root);
}
for(int i=1;i<=n;i++)
cout<<fa[i]<<' ';
cout<<endl;
return 0;
}
用链表存储二叉树
//11.51 - 12.26
#include<iostream>
using namespace std;
const int N = 1e5 +10;
int a[N],b[N];
typedef struct Node{
int val;
struct Node *left,*right;
}Node;
void insert(Node *root,int x){ //将x插入以root节点后面
if(x > root->val) //插到右儿子
if(root -> right) insert(root -> right,x);
else{
root -> right = (Node*)malloc(sizeof(Node));
root -> right -> val = x;
b[x] = root -> val;
}
else //插到左儿子
if(root -> left) insert(root -> left,x);
else{
root -> left = (Node*)malloc(sizeof(Node));
root -> left -> val = x;
b[x] = root -> val;
}
}
int main(){
int n;
cin >> n;
int x;
cin >> x;
Node *root = (Node*)malloc(sizeof(Node));
root -> val = x;
for(int i = 2;i <= n;i++){
cin >> x;
insert(root,x);
}
for(int i = 1;i <= n;i++) cout << b[i] << ' ';
return 0;
}
以上做法都需要建树。搜索二叉树最坏时间复杂度为n^2。所以估计都会超时。可能还需要优化。不过我目前的水平只能做到这里了。0.0
转自其他博客的一种思路
E 序列
状态定义:f[i][j]表示b数组中第i 个选j时前i个数的最小总权值。
状态划分:根据第j个数选0-9来枚举所有状态。当j确定时,还需要遍历b数组中第i-2个数的所有状态才能得出j确定时的最小值
f[i][j] = min(f[i][j],f[i - 1][k] + abs(a[i] - j) + (j - k) ^ 2
遇到的问题:
1、刚开始知道用动态规划的思路,但是思路想偏了。刚开始的思路是先确定b数组中第一个数,再确定第二个...以此类推,但发现按这个思路第一个数是无法确定的。思路想偏的原因还是对DP思想理解不透彻,DP问题关键在于将大问题分解为相似的若干可以解决的小问题,大问题的解决建立在小问题已经解决的基础上。主要方法是枚举所有方案。然后选出符合题意的方案。
2、f数组本来定义在了main函数里,结果产生了玄学错误。。。f数组的值总是不对。不知道是不是因为自己用的在线编译器的原因。排查了好久,最后把f数组定义成了全局变量就好了。这种错误真的折磨人...
#include<bits/stdc++.h>
using namespace std;
vector<int> a;
int f[10][10];
int main(){
int n;
cin >> n;
for(int i = 0;i < n;i++)
{
int x;
cin >> x;
a.push_back(x);
}
memset(f,0x3f,sizeof f);
for(int i = 0;i < n;i++)
for(int j = 0; j < 10;j++)
if(i)
for(int k = 0;k < 10;k++)
f[i][j] = min(f[i][j],f[i - 1][k] + abs(a[i] - j) + (j - k) * (j- k));
else
f[i][j] = abs(a[i] - j);
int maxm = 0x3f3f3f3f;
for(int i = 0;i < 10;i++){
maxm = min(maxm,f[n - 1][i]);
}
cout << maxm;
return 0;
}