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