1、EPIC Institute of Technology Round Summer 2024
的简单题(A--D)的补题,虽然我每场都只会前两道 :(((
C:Basil's Garden
思路:这道题我们会发现每一个花朵前方的花朵高会直接影响后面的花朵,所以第一反应这是一道动态规划的题目,思考后发现,高度为0的花,永远是从最后一个向前推进的,也就是说,当最左边的花高度为0时,所有的花朵都为0了。所以从右向左考虑,我们会发现相邻两朵花之间有这样两种可能关系:1. 第i-1朵会和i朵齐平,此时,i-1朵变为0的时间,就是i朵变为0之后再+1 2.第i-1朵始终比第i朵高,此时i-1朵每秒都会减1,时间为它本身的高度,即 i-1朵变为0的时间 = max(i-1朵高度,i朵变为0时间+1)。我们最终结果就是第一朵变为0的时间
AC代码 :
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 1e5+10;
#define endl "\n"
const int mod = 1e9+7;
int a[maxn];
int ans =0;
void fast ()
{ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);}
void solve ()
{
int n; cin >> n;
for(int i=1;i<=n;i++){
cin >> a[i];
}
int ans = a[n];
for(int i= n-1;i>=1;i--){
ans = max(ans+1 , a[i] );
}
cout<<ans<<endl;
memset(a,0, sizeof(a));
}
signed main ()
{
fast();
int q; cin>>q;
while (q--){
solve();
}
}
D. World is Mine
思路:想一想就会发现A的思路很明确:我就是要吃最小的就好了,但是Bob要考虑的就多了。。。Bob每次只有把这种美味值蛋糕清零,才能阻止A吃掉这一个蛋糕,我们很容易想到我们真正进行研究的数组,其实是不同美味值蛋糕的数量。比如: 1 1 4 5 1 4,我们需要把他变化为:3 2 1(从小到大美味值蛋糕数量),然后Bob能把多少蛋糕数量清零,A就能吃剩下的蛋糕。我们想一下会发现这好像是一个背包问题,不过Bob背包大小是变化的,或者说A吃了几次,那么Bob背包容量就是多少,并且背包容量其实就是A吃蛋糕次数。还有一点需要注意的地方是:
容量:0 | 1 | 2 | 3 | 4 |
1 | 2 | 3 | 4 | 5 |
2 | 3 | 4 | 5 |
这一组数据:当背包容量为4时,按理论Bob可以吃掉美味值3和5的全部蛋糕,但是试一试我们发现:B在吃完美味值3的蛋糕之后,A时先吃的,也就是说,容量为4时吃不完最后两块,需要再多1个容量!所以我们再状态转移的时候使用dp[j+1]代替dp[j]
AC代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
void fast ()
{ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);}
const int maxn = 5050;
int a[maxn];
int dp[maxn];
void solve ()
{
int n; cin >> n;
vector<int> vis;
for(int i=1; i<=n;i++){
int x; cin >>x;
a[x]++;
}
for(int i=1;i<=5000;i++)
if(a[i]) vis.push_back(a[i]); //vis就是处理后的数组
int m = vis.size(); //m就是背包问题中物品数量
for(int i=1 ;i<m;i++){
for(int j=i;j>=0;j--){
if(j >=vis[i]) {
dp[j+1] = max(dp[j-vis[i]]+1, dp[j+1]);
}
}
}
int mx =0;
for(int i=0;i<=m;i++){
mx = max(mx,dp[i]); //找出dp数组中最大值,也就是Bob可以清零的蛋糕种类
}
cout<<m-mx<<endl;
memset(a,0,sizeof(a));
memset(dp,0,sizeof(dp));
}
//这是原版背包的两种写法
/*for(int i=1; i<=m;i++){
for(int j= t ;t>=0;j--){
if(j>=w[i])
dp[i][j] = max(dp[i-1][j-w[i]]+v[i], dp[i-1][j]);
else dp[i][j] = dp[i-1][j];
}
for(int i=1; i<=m;i++){
for(int j= t ;t>=0;j--){
if(j>=w[i])
dp[j] = max(dp[j-w[i]]+v[i], dp[j]);
}
}*/
signed main ()
{
fast();
int t; cin >>t;
while(t--){
solve();
}
return 0;
}