[算法设计]代码复习笔记

考试内容

分治算法

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;
}

参考资料

https://www.luogu.org/problemnew/solution/P1115 最大子段和

动态规划

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章