开始: 2023-08-12 12:45:00

0812算法班(3期)期末测试

结束: 2023-08-12 15:40:25
当前  2025-01-24 18:01:46  类型: OI  状态: 已经结束 

T1牛奶供应

考察的是队列,那我们把内容放入队列,过期的就出队,没过期的就统计,统计的时候考虑能不能收购!

	while (r <= n) {
		if (r-l > m) l++;
		while (l<=r && c[r]!=0) {
			if (p[l] <= c[r]) {
				sum += p[l];
				c[r] -= p[l];
				l++;
			} else {
				sum += c[r];
				p[l] -= c[r];
				c[r] = 0;
			}
		}
		r++;
	}

T2算24

考察内容为dfs,设计dfs的时候,要考虑放下的符号有优先级,当然,可以利用栈对表达式进行计算。

这里利用dfs枚举出符号,然后利用堆栈进行计算!

bool cal()
{
	stack<int>num;
	stack<int>op;
	num.push(a[1]);
	for(int i=2;i<=n;i++)
		if(t[i]==3)
		{
			int s=num.top()*a[i];
			num.pop();
			num.push(s);
		}
		else num.push(a[i]),op.push(t[i]);
	while(!op.empty())
	{
		int y=num.top();num.pop();
		int x=num.top();num.pop();
		int z=op.top();op.pop();
		if(z==1) num.push(x+y);
		else num.push(x-y);
	}
	if(num.top()==24) return true;
	else return false;
}

T3货币系统

考察DP,完全背包,具体转移看解释

  f[0]=1;//上面是面值,f[i]表示面值为i时方案数,0初始为1,因为唯一的方案就是不放钱
  for(int i=1; i<=v; ++i) //枚举每种面值
    for(int j=p[i]; j<=n; ++j) //这也是完全背包写法,可无限用,如果j<该面值无需枚举,如果j>总数不合题意了(浪费时间)
      f[j]=(f[j]+f[j-p[i]])%mod;//因为从前往后,更新j面值时的方案数

T4观光车

因为每个观光车只能坐两个人,所以考虑一个策略,就是排序后,左右指针枚举,算法时间复杂度O(N)

考察 sort+双指针

    sort(a + 1, a + n + 1);//排序
    int left = 1;//左指针指向最轻的人
    int right = n;//右指针指向最重的人
    while (left < right) {//直到指针重合
        if (a[left] + a[right] <= t) {//如果可以配对
            ans++;//用一辆车
            left++;//左加
            right--;//右减
        } else {//如果不能配对
            ans++;//给体重重的单独配一辆车
            right--;//右减
        }
    }    if (right == left) ans++;//如果最后剩一个人,单独用一辆车

T5回文游戏

区间DP,考虑i和j相等的时候,直接由dp[i+1][j-1]转移过来呢?如果不相等,考虑DP[i][j-1]或者DP[i+1][j]更优解而来

	for(int len = 2; len <= n; len++){
		for(int i = 1; i + len - 1 <= n; i++){
			int j = i + len - 1;
			//必须要有j - i > 1,因为j - i == 1这种情况在初始化已经被更新了,且是最优值
			//为什么当相等的时候,直接由dp[i+1][j-1]转移过来呢?
			//因为区间[i+1,j-1]合并到最后会剩下一个回文串,回文串两端加上相同的字母还是回文串,合并次数不变 
			if(a[i] == a[j] && j - i > 1) {
				dp[i][j] = dp[i + 1][j - 1];
			}
			for(int k = i; k < j; k++){
				dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j]);
			}
		}
	}

T6多边形划分

区间DP,考虑2条边是没办法构成三角形的,所有初始化为0,三条边的时候,利用k进行划分,dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j] + i * k * j);

	for(int len = 2; len <= n; len++){
		for(int i = 1; i + len - 1 <= n; i++){
			int j = i + len - 1;
			for(int k = i; k < j; k++){//其他题目区间是不包含关系,所以是k+1
				dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j] + i * k * j);
			}
		}
	}