考试内容
分治算法
B - 整数因子分解问题
#include<bits/stdc++.h>
using namespace std;
//用map开一个数组(大)
map<int ,int >a;
int f(int n){
if(n == 1)
return 1;
if(a[n])
return a[n];
//curCount为n的分解数,初始值为1(自己是自己的因子)
int curCount=1;
for(int i=2;i<=sqrt(n);i++){
if(n%i == 0){
curCount+=f(i);
//因为循环到sqrt(n),如果n/i此时的值
//不等于i,则继续分解n/i,并将返回的结果
//加到curCount上
if(i!=n/i){
curCount+=f(n/i);
}
}
}
a[n] = curCount;
return a[n];
}
int main()
{
int n;
while(cin>>n){
cout<<f(n)<<endl;
}
}
C - 顺序表应用7:最大子段和之分治递归法
#include<bits/stdc++.h>
using namespace std;
int n,arr[200200];//开数组存数字
int c= 0;//递归次数
int rec(int l,int r){
int sum = 0;
c++;
//当左右相等时
if(l==r){
if(arr[l]>=0)
sum = arr[l];
else
sum = 0;
}
else
{
int mid = (l+r)>>1;
int leftsum = rec(l,mid);
int rightsum = rec(mid+1,r);
int s1,s2,ss;
s1 = ss =0;
for(int i=mid;i>=l;--i){
ss+=arr[i];
s1 = max(ss,s1);
}
s2 = ss =0;
for ( int i=mid+1;i<=r;++i){
ss+=arr[i];
s2 = max(ss,s2);
}
sum = max(max(s1+s2,leftsum),rightsum);
}
return sum;
}
int main(){
scanf("%d",&n);
for(int i = 0; i<n; ++i)
scanf("%d", &arr[i]);
cout<<rec(0,n-1)<<" "<<c<<endl;
return 0;
}
参考资料
动态规划
B - 最少硬币问题
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
int dp[20020];
int main(){
int n;
cin>>n;
int coins[n];
int T[n];
for(int i=0;i<n;i++){
cin>>T[i]>>coins[i];
}
int m;
cin>>m;
for(int i=1;i<=m;i++) dp[i]=INF;
for(int i=0;i<n;i++)
for(int j=1;j<= coins[i];i++)
for(int k=m;k>=T[i];k--)
dp[k]=min(dp[k],dp[k-T[i]]+1);
cout<<(dp[m]<m?dp[m]:-1)<<endl;
}
D - 石子合并问题
暂无
E - 最长公共子序列问题
#include<bits/stdc++.h>
using namespace std;
int findLCS(string A, string B)
{
int n= A.length(),m=B.length();
if(n == 0 || m == 0)//特殊输入
return 0;
int dp[n + 1][m + 1];//定义状态数组
for(int i = 0 ; i <= n; i++)//初始状态
dp[i][0] = 0;
for(int i = 0; i <= m; i++)
dp[0][i] = 0;
for(int i = 1; i <= n; i++)
for(int j = 1; j<= m; j++)
{
if(A[i - 1] == B[j - 1])//判断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]);
}
return dp[n][m];//最终的返回结果就是dp[n][m]
}
int main()
{
int n;
string s1,s2;
while(cin>>s1){
cin>>s2;
cout<<findLCS(s1,s2)<<endl;
}
}
贪心算法练习
A 2072] - 删数问题
#include <bits/stdc++.h>
using namespace std;
int main()
{
string a;
int n,i,j,k;
cin>>a>>n;
int len=a.size();
for(k=0;k<n;k++) //这个循环控制删数的次数
{
for(i=0;i<len-1;i++) //这个循环比较此位和下一位的大小
{
if(a[i]>a[i+1]) //删数
{
for(j=i;j<len-1;j++)
a[j]=a[j+1];
break; //删完数后,应该跳出循环,进行下一次找数删数(break不能跳出if);n次删数;
}
}
len--; //如果不满足条件 (都是递增的数),那么长度直接减1;适用于123456这种情况;其实不管满 不满足比较的条件,长度都会减1
}
i=0;
while(i<=len-1&&a[i]=='0')
i++;
if(i==len)
cout<<"0"<<endl;
else
for(j=i;j<=len-1;j++)
cout<<a[j];
return 0;
}
活动选择
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
struct node{
int _num;
int _beg;
int _end;
}a[101];
bool cmp(node a,node b){
return a._end < b._end;
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i]._beg>>a[i]._end;
a[i]._num = i+1;
}
sort(a,a+n,cmp);
int mmax = a[0]._end;
cout<<a[0]._num;
for(int i=1;i<n;i++)
{
//cout<<a[i]._num<<" "<<a[i]._beg<<" "<<a[i]._end<<endl;
if(a[i]._beg>=mmax){
cout<<","<<a[i]._num;
mmax = a[i]._end;
}
}
}
活动选择问题
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
struct node{
int _num;
int _beg;
int _end;
}a[101];
bool cmp(node a,node b){
return a._end < b._end;
}
int main(){
int n;
while(cin>>n){
for(int i=0;i<n;i++)
{
cin>>a[i]._beg>>a[i]._end;
a[i]._num = i+1;
}
sort(a,a+n,cmp);
int mmax = a[0]._end;
//cout<<a[0]._num;
int sum= 1;
for(int i=1;i<n;i++)
{
//cout<<a[i]._num<<" "<<a[i]._beg<<" "<<a[i]._end<<endl;
if(a[i]._beg>=mmax){
sum++;
mmax = a[i]._end;
}
}
cout<<sum<<endl;
}
}
D 2074] - 区间覆盖问题
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
struct node{
int bg;
int ed;
}a[201];
int b[201];
bool cmp(node a,node b){
return a.ed<b.ed;
}
bool cmp1(int a,int b){
return a>b;
}
int main(){
int n;
int m;
while(cin>>n){
cin>>m;
for(int i=0; i<n;i++){
cin>>a[i].ed;
a[i].bg = a[i].ed-1;
}
sort(a,a+n,cmp);
int s = a[n-1].ed-a[0].bg;
for(int i=0; i<n-1;i++){
// cout<<a[i].bg<<" "<<a[i].ed<<endl;
b[i]= a[i+1].bg-a[i].ed;
}
sort(b,b+n-1,cmp1);
if(m>=n)
s = n;
else
for(int i=0;i<m-1;i++)
s-=b[i];
cout<<s<<endl;
}
}
E 最少拦截系统
#include<bits/stdc++.h>
using namespace std;
int main(){
int m,n;
while(cin>>n){
int a[100];
int sum= 1;
cin>>a[0];
int j;
for(int i=1;i<n;i++){
cin>>m;
int f=0;
for(int j=0;j<sum;j++){
if(a[j]>= m ){
a[j] = m;
f=1;
break;
}
}
if(f==0)
a[sum++]=m;
}
cout<<sum<<endl;
}
}
搜索回溯框架
整数变换问题
#include<bits/stdc++.h>
using namespace std;
int cnt = 0,cn = 0;
char a[10010];
int fun(int i, int sum) //分别计算两种函数
{
if(i == 0)
return sum*3;
else
return sum/2;
}
bool traceback(int n, int m, int dept)
{
if(dept > cnt) //当前的深度不能使n变成m
return false;
int sum = n;
for(int i = 0; i < 2; i++)
{
sum = fun(i,n);
if(sum == m || traceback(sum,m,dept+1))
{
if(i == 0)
a[cn++] = 'f';
else
a[cn++] = 'g';
return true;
}
}
return false;
}
int main()
{
int n,m;
cnt = 1;
cin>>n>>m;
while(!traceback(n,m,1))
{
cnt++;
}
cout<<cnt<<endl;
for(int i = 0; i < cn; i++)
cout<<a[i];
return 0;
}