2024牛客寒假算法基础集训营2个人补题题解(K、D)
比赛链接:2024牛客寒假算法基础集训营2
K、Tokitsukaze and Password (easy)
题面看着很难实际上只要暴力的东西,赛时看了眼题面就溜了血亏
爆搜,枚举\(abcd\)和_可能的值,枚举的情况只有\(9*8*7*6*9=27216\)种。判断按照枚举出的对应值排列出的密码是否满足条件,满足就\(ans++\)
写完以后发现大概也不需要dfs,直接五层循环就行。
ac代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
const int inf=1e18;
const int M=1e9+7;
bool vis[20];
map<int,int> mp;
int v[N];
int n;
int lim;
int ans;
string s;
void dfs(int cnt)
{
if(cnt==5)
{
int p=0;
string now;
for(int i=0;i<n;i++)
{
char c;
if(isdigit(s[i]))
now+=s[i],p=p*10+s[i]-'0';
else
{
if(isalpha(s[i]))
c=v[s[i]-'a'+1]+'0';
else c=v[5]+'0';
now+=c;
p=p*10+(c-'0');
}
}
if(n==1&&p==0&&mp[p]==0)
ans++,mp[p]=1;
else if(p%8==0&&p<=lim&&mp[p]==0&&now[0]!='0')
ans++,mp[p]=1;
return ;
}
for(int i=0;i<=9;i++)
{
if(cnt!=4)
{
if(vis[i]==0)
{
v[cnt+1]=i;
vis[i]=1;
dfs(cnt+1);
vis[i]=0;
}
}
else
{
v[cnt+1]=i;
dfs(cnt+1);
}
}
}
signed main() {
int t;
cin >>t;
while(t--)
{
memset(vis,0,sizeof(vis));
mp.clear();
cin >>n;
cin >>s>>lim;
ans=0;
dfs(0);
cout<<ans<<'\n';
}
return 0;
}
D、Tokitsukaze and Slash Draw
需要考虑的只有居合卡位置,先后是怎么摆的及其他卡的位置不需要考虑,很明显的多重背包,而且对于某一张卡来说最多使用\(n\)次,\(n\)次以上一定会发生位置的重复,但是如果直接上多重背包模板时间复杂度会来到\(O(m^2n)\)会t掉。
预处理\(up\)数组,定义\(up\)[\(i\)]为使当前位置上升\(i\)位置的最小花费。
定义\(dp\)[\(i\)][\(j\)]为在当前居合卡的位置为j时最多移动了i个位置的最小花费。
状态转移:\(dp\)[\(i\)][\((i+j)%n\)]\(=\)\(min(dp\)[\(i\)][\((i+j)%n\)]\(,dp\)[\(i-1\)][\(j\)]\(+up[i])\)
最后答案就是\(dp\)[\(n\)][\(0\)](当前居合卡在\(0\)位置时,最多向上移动了\(n\)个位置的最小花费)
时间复杂度:\(O(mn+n^2)\)
还有图论做法和别的dp做法,但是脑子不太好使暂时只搞懂了这种(
自己的ac代码是特判了\((i+j)\)%\(n\)=0的时候让它等于\(n\),不过实测不搞特判也能过,内循环初始值设为\(0\)就行。
ac代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
const int inf=1e18;
const int M=1e9+7;
int up[5050];
int dp[5050][5050];
signed main() {
int t;
cin >>t;
while(t--)
{
int n,m,k;
cin >>n>>m>>k;
// k-=1;
for(int i=0;i<=max(n,m);i++)
{
for(int j=0;j<=max(n,m);j++)
dp[i][j]=up[j]=inf;
}
for(int i=1;i<=m;i++)
{
int p,cost;
cin >>p>>cost;
for(int j=1;j<=n;j++)
{
int next=(j*p)%n;
if(next==0) next=n;
up[next]=min(up[next],cost*j);
}
}
dp[0][k]=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
dp[i][j]=dp[i-1][j];
for(int j=1;j<=n;j++)
{
int next=(i+j)%n;
if(next==0) next=n;
dp[i][next]=min(dp[i][next],dp[i-1][j]+up[i]);
}
}
if(dp[n][n]!=inf)
cout<<dp[n][n]<<'\n';
else cout<<-1<<'\n';
}
return 0;
}

浙公网安备 33010602011771号