首页 > 试题广场 >

队列得分

[编程题]队列得分
  • 热度指数:2192 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解

M和大M要通过选择元素组成队列进行得分pk。目前存在队列S1,S2,S3...Sn,每个元素包括2个正整数属性setvalue.从中选出任意K个元素S[i1],S[i2]...S[ik],保证顺序不变即i1 < i2 < i3< ... < ik,组成新的队列P1,P2,P3......Pk.我们通过一个机制评价队列的好坏:

Base=P1.value+P2.value+...Pk.value,

Bonus=10*t;t为新队列中Pi.set=P(i+1).seti个数.

最终得分Score=Base-Bonus;Score的最大值和取最大值时新队列元素个数的最小值.


输入描述:
第一行包含一个数N(0 < N <= 500)

接下来N行每一行两个数表示S1,S2,...,Sn的set和value值 (0 < set,value <= 20)


输出描述:
Score的最大值和新队列元素个数的最小值
示例1

输入

5
1 10
1 5
2 4
3 9
4 8

输出

31 4

说明

选S1,S3,S4,S5
""""
动态规划求解,或DFS
参考@无心2019 代码,设dp[n]为选中Si且以Si结尾的最大值,
dp[n] = max{ dp[0]+Score, dp[1]+Score, ... ,dp[n-1]+Score, Base }
"""


class node:
    def __init__(self, set, value):
        self.set = set
        self.value = value


if __name__ == "__main__":
    N = int(input())
    S = []
    for _ in range(N):
        a, b = map(int, input().strip().split())
        S.append(node(a, b))
    dp, cnt = [], []
    for j in range(N):
        t_max, t_cnt = 0, 0
        for i in range(j):
            tmp = dp[i] - 10 * (1 if S[i].set == S[j].set else 0)
            if tmp > t_max:
                t_max = tmp
                t_cnt = cnt[i]
            elif tmp == t_max:
                t_cnt = min(t_cnt, cnt[i])
        dp.append(t_max + S[j].value)
        cnt.append(t_cnt + 1)
    ans_max, ans_cnt = 0, 0
    for i in range(N):
        if ans_max < dp[i]:
            ans_max = dp[i]
            ans_cnt = cnt[i]
        elif ans_max == dp[i]:
            ans_cnt = min(ans_cnt, cnt[i])
    print(ans_max, ans_cnt)
编辑于 2019-07-16 17:41:35 回复(0)
//用unordered_map即可,在输入做判断
#include<iostream>
(720)#include<unordered_map>
#include<vector>
using namespace std;
int main()
{
    int n;
    cin>>n;
    int set,value;
    unordered_map<int,vector<int>> m;
    int set11,value11;
    while(n)
    {
        cin>>set>>value;
        if(set11!=set||value>value11||value>10)
        {
            if(set11!=set)
                m[set].push_back(value);
            else
            {
                if(value11>10)
                    m[set].push_back(value-10);
                else
                    m[set11][m[set11].size()-1]=value;
            }
            set11=set;
            value11=value;
        }
        n--;
    }
    int sum=0,num=0;
    for(auto it:m)
    {
        for(auto ot:it.second)
        {
            sum+=ot;
            num++;
        }
    }
    cout<<sum<<" "<<num;
}

发表于 2020-04-21 10:00:29 回复(0)
#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    cin>>n;
    int s[n][2];
    for(int i=0;i<n;i++)
        cin>>s[i][0]>>s[i][1];
    int dp[n],num[n];
    int i, j, ans = 0, ansNum = 0, cur, curNum;
    for (i = 0; i < n; ++i)
    {
        cur = curNum = 0;
        for (j = 0; j < i; ++j)
        {
            if (cur < dp[j] - (s[i][0] == s[j][0] ? 10 : 0))
            {
                cur = dp[j] - (s[i][0] == s[j][0]? 10 : 0);
                curNum = num[j];
            }
        }
        dp[i] = cur + s[i][1];
        num[i] = curNum + 1;
        if (ans < dp[i])
        {
            ans = dp[i];
            ansNum = num[i];
        }
    }
    cout<<ans<<" " <<ansNum<<endl;
    return 0;
}

发表于 2019-07-09 18:18:39 回复(0)
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

/*
O(n)复杂度即可
其实是分类讨论问题:
把连续具有相同set的元素看做一个小组,对于每一组,如下操作:
1. 该组所有的value都<=10,则只选取1个最大的元素;
2. 该组存在1个或多个元素>10,则选取所有>10的元素(假设为N个),
总分记录为value之和减去(N-1)*10
最后把所有组的和加起来就可以啦
写法函数化了且比较易懂,供参考讨论
*/

struct prs{
    int s;
    int v;
};

struct res{
    int maxval;
    int numval;
};


res score_fun(vector<prs> &vec) {
    res r;
    int i, nowset, cc;
    int p10, pres10, mres10;
    r.maxval = 0;
    r.numval = 0;
    nowset = vec[0].s -1;
    
    i = 0;
    while(i < vec.size()) {
        p10 = 0;
        pres10 = 0;
        mres10 = 0;
        cc = i;
        while(cc < vec.size() && vec[cc].s == vec[i].s) {
            if(vec[cc].v <= 10) {
                mres10 = max(mres10, vec[cc].v);
            }
            else {
                pres10 = pres10 + vec[cc].v;
                p10++;
            }
            cc++;
        }
        if(p10 > 0) {
            r.maxval = r.maxval + pres10 - (p10-1)*10;
            r.numval = r.numval + p10;
        }
        else {
            r.maxval = r.maxval + mres10;
            r.numval = r.numval + 1;
        }
        i = cc;
    }
    
    return r;
}


int main() {
    int N;
    cin>>N;
    prs ptmp;
    res r;
    vector<prs> vec;
    int i;
    
    for(i = 0; i < N; i++) {
        cin>>ptmp.s>>ptmp.v;
        vec.push_back(ptmp);
    }
    
    r = score_fun(vec);
    cout<<r.maxval<<" "<<r.numval<<endl;
    return 0;
}

编辑于 2020-03-21 15:26:34 回复(0)
import java.util.*;
import java.lang.*;
import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int length = Integer.parseInt(br.readLine());
        String[] arr0 = br.readLine().split(" ");
        int t1 = Integer.parseInt(arr0[0]);
        int t2 = Integer.parseInt(arr0[1]);
        int sum = t2;
        int eqnum = 0;
        String line = "";
        while ((line = br.readLine()) != null) {
            String[] arr = line.split(" ");
            int a = Integer.parseInt(arr[0]);
            int b = Integer.parseInt(arr[1]);
            if (a == t1) {
                if (t2 <= 10 || b <= 10) {
                    b = Math.max(b, t2);
                    length--;
                } else {
                    t2 = 0;
                    eqnum++;
                }
            } else {
                t2 = 0;
            }
            sum += b - t2;
            t1 = a;
            t2 = b;
        }
        System.out.println((sum - eqnum * 10) + " " + length);
    }
}

编辑于 2024-02-22 09:52:39 回复(0)
n = int(input())

prest = 0
prevl = 0

score = 0
bonus = 0
count = 0

for i in range(n):
    st , vl = map(int,input().split())
    if st != prest:
        score += vl
        count += 1
    if st == prest:
        if vl > 10 and prevl > 10:
            score += vl
            count += 1
            bonus += 10
        else:
            if prevl >= vl:
                continue
            if prevl < vl:
                score -= prevl 
                score += vl
    prest , prevl = st , vl

print(score - bonus , count)

发表于 2023-04-16 22:48:54 回复(0)
#include <bits/stdc++.h>
using namespace std;

void groupData(map<int, pair<vector<int>, vector<int>>> &pMap, int &que, int &sumBonus, int &base) {
    int bonus = -1;
    for (auto it=pMap.begin(); it!=pMap.end(); it++) {
        if (it->second.second.empty()) {        // 所有元素 <= 10
            base += *max_element(it->second.first.begin(), it->second.first.end());
            que++;
        } else {                   // 选取所有 >10 的部分 
            for (auto val : it->second.second) {
                base += val;
                bonus += 1;
                que += 1;
            }
            sumBonus += bonus;
        }  
    }
    pMap.clear();
}

int main() {
    int N; cin >> N;
    map<int, pair<vector<int>, vector<int>>> pMap;
    int tmpSet, set, value; cin >> set; cin >> value; tmpSet = set;
    int base = 0, sumBonus = 0, que = 0;
    while (N-- >= 0) {
        if (tmpSet != set || N==-1) {
            tmpSet = set;
            groupData(pMap, que, sumBonus, base);
            if (value <= 10) pMap[set].first.push_back(value);  // <= 10 的部分
            else pMap[set].second.push_back(value);             // > 10 的部分
            
        } else {
            if (value <= 10) pMap[set].first.push_back(value);  // <= 10 的部分
            else pMap[set].second.push_back(value);             // > 10 的部分
        }
        cin >> set; cin >> value;
    }
    cout << (base - sumBonus*10) << " " << que;
    return 0;
}

发表于 2022-05-25 14:31:29 回复(0)
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int sum = 0;int count = n;
        int tempSet = 0;
        int tempVal = 0;
        for(int i = 0; i < n; i++){
            boolean flag = false;
            int set = sc.nextInt();
            int value = sc.nextInt();
            if(set == tempSet){
//                 两个都比10大,都加入
                if(10 < tempVal && 10 < value){
                    sum -= 10;
                }else{
                    //一个比10大,或者都没有10大,加一个
                    if(tempVal < value){
                        sum -= tempVal;
                    }else{
                        sum -= value;
//                         是为了让tempVal为之前的数
                        flag = true;
                    }
                    count--;
                }
            }
            tempSet = set;
            if(!flag) 
                tempVal = value;
            sum += value;
        }
        System.out.print(sum+" "+count);
    }
}
发表于 2021-12-04 15:08:17 回复(0)
#include <iostream>
using namespace std;
int main(){
	int n,set,val;
	int sum=0;
	int last_set=-1;
	int flag=0,currval=0,num=0;
	cin>>n;
	for(int i=0;i<=n;i++){
		if(i==n){
			set=-1;val=-1;
		}
		else
			cin>>set>>val;
		if(last_set!=set){
			if(!flag){
				sum+=currval;num++;
			}
			else{
				flag=0;currval=0;
			}
			last_set=set;
			if(val>10){
				sum+=val;flag=1;num++;
			}
			else
				currval=val;			
		}else{
			if(val>10){
				num++;
				if(flag)
					sum+=val-10;
				else{
					sum+=val;flag=1;
				}
			}
			else 
				if(val>currval)
					currval=val;
		}

	}
	cout<<sum<<" "<<num-1<<endl;
	return 0;
}


发表于 2020-02-11 17:08:39 回复(0)
vector<pair<int, int>> vec存放元素, first代表set,second代表value,开始存一个初始值(-1,0);

dp[i][1]表示从第1个到第i个元素,以第i个元素结尾的Score的最大值;dp[i][0]表示从第1个到第i个元素,不以第i个元素结尾的Score的最大值。
dpcnt[i][1]表示从第1个到第i个元素,以第i个元素结尾的Score最大时的元素个数;dp[i][0]表示从第1个到第i个元素,不以第i个元素结尾的Score最大时的元素个数。

递归方程:
dp[i][0] = max(dp[i][0], max(dp[k][0], dp[k][1])) ,  0 <= k < i; 
dp[i][1] = max(dp[i][1], dp[k][1] + vec[i].second - 10 * (vec[i].first == vec[k].first)), 0 <= k < i;
注:
不以第i个元素结尾,所以前一个元素以第几个结尾不重要。
以第i个元素结尾,所以我们必须知道前一个元素的值是什么。

dpcnt[i][0] 等于使得dp[i][0]为最大时的相对应的dp[k][0/1]的元素个数dpcnt[k][0/1]
dpcnt[i][1] 等于使得dp[i][1]为最大时的相对应的dp[k][1]的元素个数dpcnt[k][0/1] + 1, 加1为加上当前的i这个元素。

#include <iostream>
#include <vector>
using namespace std;

int main() 
{
    int n;
    cin >> n;
    vector<pair<int, int>> vec(n + 1);
    vec[0].first = -1;
    vec[0].second = 0;
    for (int i = 1; i <= n; ++i)
    {
        cin >> vec[i].first >> vec[i].second;
    }

    vector<vector<int>> dp (n + 1, vector<int>(2, 0));
    vector<vector<int>> dpcnt(n + 1, vector<int>(2, 0));
    for (int i = 1; i <= n; ++i)
    {
        for (int k = 0; k < i; ++k)
        {
            if (dp[i][0] < max(dp[k][0], dp[k][1]))
            {
                dp[i][0] = max(dp[k][0], dp[k][1]);
                if (dp[k][0] < dp[k][1])
                {
                    dpcnt[i][0] = dpcnt[k][1];
                }
                else
                {
                    dpcnt[i][0] = dpcnt[k][0];
                }
            }

            if (dp[i][1] < dp[k][1] + vec[i].second - 10 * (vec[i].first == vec[k].first))
            {
                dp[i][1] = max(dp[i][1], dp[k][1] + vec[i].second - 10 * (vec[i].first == vec[k].first));
                dpcnt[i][1] = dpcnt[k][1] + 1;
            }
        }
    }

    if (dp[n][0] < dp[n][1])
    {
        cout << dp[n][1] << " " << dpcnt[n][1] << endl;
    }
    else
    {
        cout << dp[n][0] << " " << dpcnt[n][0] << endl;
    }
    system("pause");
}
发表于 2019-09-14 22:52:30 回复(0)
if __name__=='__main__':
    try:
        while True:
            N = input().strip()
            if N == '':
                break
            else:
                N = int(N)
                if N == 1:
                    set, value = map(int, input().strip().split())
                    print(value, '1')
                else:
                    l_set = []
                    l_value = []
                    for j in range(N):
                        set, value = map(int, input().strip().split())
                        l_set.append(set)
                        l_value.append(value)
                    p_set = [l_set[0],]
                    p_value = [l_value[0],]
                    bonus = 0
                    for i in range(1, N):
                        if l_set[i]==p_set[-1]:
                            if p_value[-1] > 10:
                                if l_value[i]>10:
                                    bonus = bonus + 1
                                    p_set.append(l_set[i])
                                    p_value.append(l_value[i])
                            else:
                                if l_value[i]>p_value[-1]:
                                    p_set.pop(-1)
                                    p_value.pop(-1)
                                    p_set.append(l_set[i])
                                    p_value.append(l_value[i])
                        else:
                            p_set.append(l_set[i])
                            p_value.append(l_value[i])
                print(sum(p_value) - 10 * bonus, len(p_value))
    except:
        pass

发表于 2019-04-16 16:27:37 回复(0)