【无标题】

文章展示了几个C++编程示例,涉及动态规划在解决背包问题和代码竞赛中的应用。第一部分是根据状态转移方程填充矩阵,第二部分是计算走步序列的方案数,第三部分是01背包问题,第四部分是处理比赛提交情况,第五部分是分配有限资源的问题。所有例子都展现了动态规划和高效算法在解决复杂问题中的重要性。
摘要由CSDN通过智能技术生成

 


#include <iostream>

using namespace std;
char tu[101][101];
int now;
int main()
{
    int n;
    cin >> n;
    now=n;
    for (int i = n; i >= n / 2; --i)
    {
        if (n % 2!=now%2)//与最外圈奇偶性不同为点
        {
            int j = i;
            while (j >= n - i + 1)
            {
                tu[n - i + 1][j] = '.';
                tu[i][j] = '.';
                tu[j][i] = '.';
                tu[j][n - i + 1] = '.';
                j--;
            }
        }
        else//与最外圈奇偶性相同为加
        {
            int j = i;
            while (j >= n - i + 1)
            {
                tu[n - i + 1][j] = '+';
                tu[i][j] = '+';
                tu[j][i] = '+';
                tu[j][n - i + 1] = '+';
                j--;
            }
        }
        --now;
    }
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= n; ++j)
        {
            cout << tu[i][j];
        }
        cout << endl;
    }
}

 根据状态转移方程,走了i-1步时无论最后走了几次二步,都能走一步到第i步,并且最后连续走的两步的次数清成0,走了i-2步时最后走j次两步的结果可以转移至走i步时最后走j+1次两步的结果,而且要注意j+1不能超过3即可。

#include <iostream>
using namespace std;
long long f[51][51];
int main()
{
    int n;
    cin>>n;
    f[0][0]=1;

    for(int i=1;i<=n;++i){
        f[i][0]=f[i-1][0]+f[i-1][1]+f[i-1][2];
        if(i<2)continue;
        f[i][1]=f[i-2][0];
        f[i][2]=f[i-2][1];
    }
    cout<<f[n][0]+f[n][1]+f[n][2];

}

 这很明显是一个背包问题,我们可以把m看作背包容量,n看为物品个数,对应值看作体积,只要最后能装下就可以

#include <bits/stdc++.h>
using namespace std;

int n, m; //n为物品个数,m为背包容量
const int N = 100005; //数组长度
long long f[505][N], a[150], b[150]; //f数组为动态规划数组,a和b数组为物品的体积和价值

int main()
{
    cin >> n >> m; //读入物品个数和背包容量
    for (int i = 0; i < n; ++i) //循环读入每个物品的体积和价值
    {
        cin >> a[i] >> b[i];
    }
    f[0][0] = 1; //初始化f[0][0]为1
    for (int i = 0; i < n; ++i) //外层循环遍历物品
    {
        for (int j = 0; j <= m; ++j) //内层循环遍历背包容量
        {
            if (f[i][j] == 1 && f[i + 1][j + a[i]] <= m) //如果能选第i个物品且加入后不超过背包容量,将f[i+1][j+a[i]]置为1
                f[i + 1][j + a[i]] = 1;
            if (f[i][j] == 1 && f[i + 1][j + b[i]] <= m) //如果能选第i个物品且加入后不超过背包容量,将f[i+1][j+b[i]]置为1
                f[i + 1][j + b[i]] = 1;
        }
    }
    for (int i = 0; i <= m; ++i) //输出f[n][i]的值
    {
        if (f[n][i]==1)
            cout << 1; //如果f[n][i]为1,则输出1
        else
            cout << 0; //否则输出0
    }
}

 

 这题通过定义结构体personproblem,分别表示参赛者和题目的信息。然后使用map类型的变量peppro,将每个参赛者的姓名和每个题目的名称映射到相应的结构体中。通过peppro,可以快速查找每个参赛者和题目的信息。在输入过程中,先输入参赛者的姓名,然后输入每个题目的名称和分值。最后,处理每个参赛者提交的代码情况,如果提交的结果为AC,则将该题的分值加到参赛者的总分中,最后输出每个参赛者的姓名和总分。

#include <bits/stdc++.h>
using namespace std;

int N, M, K;

//定义结构体person和problem
struct person
{
    string name; //姓名
    int score = 0; //分数
    bool live; //是否存在
} pe[205];

struct problem
{
    string name; //题目名
    int score = 0; //分值
    bool live; //是否存在
} pr[205];

//定义两个map类型的变量,用于实现姓名和题目名的映射关系
map<string, person> pep; 
map<string, problem> pro;

int main()
{
    cin >> N >> M >> K;

    //输入参赛者姓名
    for (int i = 0; i < N; ++i)
    {
        cin >> pe[i].name;
        pep[pe[i].name].live = 1;
        pep[pe[i].name].name = pe[i].name;
    }

    //输入题目名和分值
    for (int i = 0; i < M; ++i)
    {
        cin >> pr[i].name >> pr[i].score;
        pro[pr[i].name].live = 1;
        pro[pr[i].name].name = pr[i].name;
        pro[pr[i].name].score = pr[i].score;
    }

    string pename, prname, res;

    //处理每个参赛者提交的代码情况
    for (int i = 0; i < K; ++i)
    {
        cin >> pename >> prname >> res;
        if (pep[pename].live == 1 && pro[prname].live == 1) //如果参赛者和题目存在
        {
            if (res == "AC") //如果提交的结果为AC
            {
                pep[pename].score += pro[prname].score; //将该题的分值加到参赛者的总分中
            }
        }
    }

    //输出每个参赛者的姓名和总分
    for (int i = 0; i < N; ++i)
    {
        cout << pep[pe[i].name].name << " " << pep[pe[i].name].score << endl;
    }
}

 

 

 这道题比较简单,按照题目意思即可ac

#include <bits/stdc++.h>
using namespace std;
int dianshu[6];
int huase[6];
bool fourkind()
{
    int num=2;
    if (dianshu[1] == dianshu[2])
    {
        for (int i = 3; i <= 5; ++i)
        {
            if (dianshu[i] == dianshu[1])
                num++;
        }
    }
    else{
        for(int i=3;i<=5;++i){
            if (dianshu[i] == dianshu[2])
                num++;
        }
    }
    if(num>=4){
        return 1;
    }
    return 0;
}
bool fullhouse(){
    bool one=(dianshu[1]==dianshu[2]&&dianshu[1]==dianshu[3])&&dianshu[4]==dianshu[5];
    bool two=(dianshu[4]==dianshu[5]&&dianshu[4]==dianshu[3])&&dianshu[1]==dianshu[2];
    return one||two;
}
bool flush(){
    for(int i=1;i<=5;++i){
        bool one=huase[1]==huase[i];
        if(!one)return 0;
    }
    return 1;
}
bool straight(){
    for(int i=2;i<=5;++i){
        bool one=(dianshu[i]==dianshu[i-1]+1);
        if(!one)return 0;
    }
    return 1;
}
bool royal(){
    if(dianshu[5]==14)
    return 1;
    else return 0;
}
int main()
{
    for (int i = 1; i <= 5; ++i)
        cin >> dianshu[i];
    for (int i = 1; i <= 5; ++i)
        cin >> huase[i];
    if(royal()&&flush())cout<<"ROYAL FLUSH";
    else if(straight()&&flush())cout<<"STRAIGHT FLUSH";
    else if(fourkind())cout<<"FOUR OF A KIND";
    else if(fullhouse())cout<<"FULL HOUSE";
    else if(flush())cout<<"FLUSH";
    else if(straight())cout<<"STRAIGHT";
    else cout<<"FOLD";
}

 

#include<bits/stdc++.h>
using namespace std;
set<pair<int,int>>se;//带有自动排序的容器,将区间从小到大排序
void myinsert(int l,int r)//插入一个左大右小的区间函数
{
    if(r<l)return;
    se.insert({r,l});
}
int main(){
    int n;
    cin>>n;
    se.insert({2e9,1});
    for(int i=1;i<=n;++i){
        int x;
        cin>>x;//输入订单编号
        auto it=se.lower_bound({x,0});//找到上界界不小于x的最近区间
        if(it->second<=x)//区间的下界小于等于x,也就是x在区间内
        {
            cout<<x<<" ";//说明没有重复
            myinsert(it->second,x-1);//将区间分开,除去x,即标记x为已存在
            myinsert(x+1,it->first);
            se.erase(it);
        }
        else{//x在区间外
            cout<<it->second<<" ";//订单编号改成最近区间的下界
            myinsert(it->second+1,it->first);//除去下界这个值,标记为已存在
            se.erase(it);
        }
    }
    return 0;
}

 

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int n;
long long k;
int a[N],c[N];//a存每个人的打饭量,c存打不够饭的人的编号
//计算前x轮的打饭量
long long cal(int x)
{
    long long res=0;
    for(int i=1;i<=n;++i)
    {
        if(a[i]<=x)res+=a[i];//如果打的饭不足x,那么就把他打的饭全部吃掉
        else res+=x;//否则,只能吃x的饭
    }
    return res;
}
int main(){
    long long sum=0;
    cin>>n>>k;
    for(int i=1;i<=n;++i)
    {
        cin>>a[i];
        sum+=a[i];
    }
    if(sum<k)cout<<-1;
    else 
    {
        //二分答案
        int l=0,r=1e9;
        while(l+1<r)
        {
            int mid=l+r>>1;
            if(cal(mid)<=k)l=mid;
            else r=mid;
        }
        k-=cal(l);// k 等于剩余的打饭量,剩余的饭肯定不够再来一轮
        int total=0;
        for(int i=1;i<=n;++i)
        {
            if(a[i]>l){
                c[++total]=i; // 存下打不够饭的人的编号
            }
        }
        // 先打剩下的饭,打到 k 轮就行
    for(int i=k+1;i<=total;++i){
        printf("%d ",c[i]);

    }
    //再把剩余饭量给能打的人打
    for(int i=1;i<=k;++i)
    {
        if(a[c[i]]!=l+1)
        printf("%d ",c[i]);
    }

    }
}

 

#include <bits/stdc++.h>
using namespace std;
struct t
{
    int s, e, w;
    
} task[1005];//任务结构体,包括开始时间、结束时间和权值
int n;//任务总数
int f[1005];//动态规划数组,f[i]表示在时间i结束的任务获得的最大权值
int main()
{
    cin >> n;
    for (int i = 1; i <= n; ++i)
    {
        cin >> task[i].s >> task[i].e >> task[i].w;//输入每个任务的开始时间、结束时间和收益
    }
    for (int i = 1; i < 1001; ++i)
    {
        f[i + 1] = max(f[i + 1], f[i]);首先更新f[i+1]为f[i]的最大收益
        for (int j = 1; j <= n; ++j)
        {
            if (i == task[j].s)//如果任务j在时间i开始
            {
                f[task[j].e] = max(f[task[j].e], f[i] + task[j].w);//则更新时间task[j].e结束的任务的最大收益
            }
        }
    }
    cout << f[1000] << endl;//输出时间1000结束的任务的最大收益
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值