写在前面的话(前言)
每天无所事事真是无趣啊,作为一个将来要征战acm的优秀青年,我感到有刷点什么的必要了!
毕竟同级的acm大佬们真是太强了,跟着老师走肯定会一直被暴打下去。。去oj上刷题呢,又感觉效率 不高,太盲目,所以毅然决然买了这本书——挑战程序设计竞赛,每天刷几道,然后不太会的再在博客上总结,感觉锤爆同级大佬,夺取acm金,走向人生巅峰的日子就在眼前了,哇嘎嘎
题目按照书的目录来,从第二章开始,书上有的题,我没有总结在这的,说明题目太简单被我秒了(没办法就是这么强)
------------------贪心篇------------------
字典序最小问题poj3617
思路是将字符串翻转并与原字符串比较
#include <bits/stdc++.h>
#include <string>
using namespace std;
string s,s1,a,s2;
int main()
{
int n;
cin>>n;
int sum=0;
for(int i=0;i<n;i++)
{cin>>s2;s+=s2;}
s1=s;
while(s1.size()){
s=s1;
reverse(s.begin(),s.end());
if(s<s1)
{
cout<<s[0];sum++;
if(sum%80==0)cout<<endl;
s1.erase(s1.end()-1);//这里不是删end哦
}
else
{
cout<<s1[0];sum++;
if(sum%80==0)cout<<endl;
s1.erase(s1.begin());
}
}
return 0;
}
区间调度问题
思路:在可选的工作中,每次选取结束时间最早的工作
用到了函数upper_bound,即找数组中第一个比x大的数的下标
#include <bits/stdc++.h>
using namespace std;
int a[50],b[50];
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)cin>>a[i];//开始时间
for(int i=0;i<n;i++)cin>>b[i];//结束时间
int ed=b[0];
int cnt=1;
while(1)
{
int t=upper_bound(a,a+n,ed)-a;
if(t>=n)break;
ed=b[t];
cnt++;
}
cout<<cnt<<endl;
return 0;
}
Saruman Army(poj 3069)
这题不难,但是我用stl做,poj死活过不去,不知道卡在啥数据上了
以后回来再解决下
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int a[1005],b[50];
int main()
{
int n,r;
while(scanf("%d%d",&r,&n)){
if(r==-1&&n==-1)
break;
for(int i=0;i<n;i++)scanf("%d",&a[i]);//开始时间
int cnt=0;
int x;
sort(a,a+n);
x=upper_bound(a,a+n,a[0]+r)-a-1;
while(x!=n)
{
x=upper_bound(a,a+n,a[x]+r)-a;
cnt++;
}
printf("%d\n",cnt);
}
return 0;
}
--------------------动态规划篇--------------
最长公共子序列问题(LCS)/2020/4/4
问题概述:给你两个序列,问你他们的最长LCS序列的长度是多少?(序列可以是不连续的,只要元素的相对位置一样)(不了解LCS问题的自行百度)
太开心了,这道题没看题解自己就做出来了,第一道完全自己推出状态转移方程的dp题,我tql,给自己orz(一眼就会做的dalao见笑了)
蒻蒟的感悟:先画一张(n+1)*(m+1)的表,更好找出规律,写出方程后也好验证
思路:dp[i][j]表示两个串前n,m个字符的最长公共序列,那么n+1 或m+1时公共序列长度也必定大于n,m的,所以继承二者最大的一个,然后当a[i]==a[j]时,公共长度+1(详见代码)
#include <bits/stdc++.h>
using namespace std;
int dp[1000][1005];//dp表示以x为尾的最长子序列的长度
string a,b;
int main()
{
int n,m;
cin>>n>>m;
cin>>a>>b;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
if(a[i]==b[j])dp[i][j]++;
}
cout<<dp[n][m]<<endl;
return 0;
}