- 👉 一 游园安排——动态规划
- 👉 二 答疑——贪心
题目链接
这就是一道求最长递增子序列的题目,知道了LIS的求法后,难点就在于怎么得满分和找最小的最长递增子序列。
LIS的动态规划求法:
设dp[ i ] 表示以 nums[ i ] 结尾的 LIS 的长度。
int dp[1000];
for (int i = 0; i < n; ++i) {
dp[i] = 1;
for (int j = 0; j < i; ++j) {
if (nums[j] < nums[i]) {
dp[i] = max(dp[i], dp[j] + 1);
}
}
}
- 对于找最长递增子序列,我们可以利用一个数组p来记录到当前名字的上一个名字索引位置,当dp[i] 取dp[j]+1的时候,p[i] = j。
- 对于找最小的,我们可以把所有的答案存到set集合里面,set会自动按字典排序,最终取begin位置上的就行。
只有70分,剩下的超时了,因为没有使用二分去优化。麻了麻了
#include
using namespace std;
int dp[1000000];
int p[1000000];
vector<string> v, v1;
int main(){
string str;
cin>>str;
//拆分
string s;
s.push_back(str[0]);
for(int i = 1; i < str.size();++i){
if(str[i] <= 'Z' && str[i] >= 'A'){
v.push_back(s);
s.clear();
s.push_back(str[i]);
}else{
s+=str[i];
}
}
v.push_back(s);
int len = 0;
for(int i = 0; i < v.size();++i){
dp[i] = 1;
p[i] = i; //上一个名字默认指向自己。
for(int j = 0 ; j < i ; ++j){
if(v[i] > v[j]){
if(dp[i] > dp[j]+1){
dp[i] = dp[i];
}else{
dp[i] = dp[j]+1;
p[i] = j; //记录上一个名字索引。
}
len = max(len, dp[i]);
}
}
}
set<string> sets; // 存储所有的结果。自动按字典序排列。
for(int i = 0 ; i < v.size(); ++i){
if(dp[i] == len){ //搜索所有长度为len的结果。
stack<string> ss; //由于是回溯搜索的,因此答案是反的,所以需要用到栈来存储输出就是正的了。
int k = i;
while(p[k] != k){ //回溯搜索寻找答案。
ss.push(v[k]);
k = p[k];
}
ss.push(v[k]);
string a;
while(!ss.empty()){
a += ss.top();
ss.pop();
}
sets.insert(a);
}
}
// for(set::iterator it=sets.begin();it!=sets.end();++it){
// cout<<*it<
// }
cout<<*(sets.begin());
return 0;
}
👉 二 答疑——贪心
题目链接
据s+a+e的大小从小到大排序,贪心累加即可。不要怀疑,就这么简单,所以比赛的时候也不要认为后面的题目一定比前面的题目难,都要尝试做。
#include
using namespace std;
#define int long long
struct Stu{
int s, a, e;
}stu[2000];
int cmp(Stu s1, Stu s2){
return s1.a+s1.e+s1.s < s2.a+s2.e+s2.s;
}
signed main(){
int n;
cin>>n ;
for(int i = 0 ; i < n ; ++i){
cin>>stu[i].s>>stu[i].a>>stu[i].e;
}
sort(stu,stu+n,cmp);
int cnt = 0;
int total = 0;
for(int i = 0 ; i< n ; ++i){
cnt += stu[i].a + stu[i].s + total;
total += stu[i].a + stu[i].s+stu[i].e;
}
cout<<cnt;
return 0;
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)