牛客小白月赛22题解(部分)

Onida ·
更新时间:2024-09-21
· 819 次阅读

链接:https://ac.nowcoder.com/acm/contest/4462
来源:nowcoder

文章目录B 树上子链(树的直径)D 收集纸片(dfs)E 方块涂色(贪心)F 累乘数字(签到)G 仓库选址(枚举)H 货物种类(差分)J 计算A+B(大数加法) B 树上子链(树的直径)

  思路:类似于树的直径问题,如果权值都为正值我们可以直接两次 bfsbfsbfs 即可,现在权值有赋值,我们可以用 dpdpdp 来解决,dp[i]dp[i]dp[i] 表示从 iii 结点出发向下走的最长子链的长度(我们以 111 号结点作为根结点)。直接 dfsdfsdfs 更新 dpdpdp 的值即可。

#include using namespace std; #define pb push_back typedef long long ll; const ll inf=0x3f3f3f3f3f3f3f3f; const int maxn=1e5+10; ll dp[maxn],ans=-inf; int w[maxn]; vectorG[maxn]; void dfs(int u,int fa){ dp[u]=w[u]; for(auto v:G[u]){ if(v==fa) continue; dfs(v,u); ans=max(ans,dp[u]+dp[v]); dp[u]=max(dp[u],dp[v]+w[u]); } ans=max(ans,dp[u]); } int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&w[i]); for(int i=1;i<=n-1;i++){ int u,v; scanf("%d%d",&u,&v); G[u].pb(v); G[v].pb(u); } dfs(1,0); printf("%lld\n",ans); return 0; } D 收集纸片(dfs)

  思路:我们可以注意到纸片的数量比较少,所以我们直接搜索出每一种情况作出判断即可。

#include using namespace std; const int maxn=15; int x[maxn],y[maxn]; bool vis[maxn]; int n,ans=INT_MAX; int dis(int i,int j){ return abs(x[i]-x[j])+abs(y[i]-y[j]); } void dfs(int now,int Min,int cnt){ if(cnt==n){ ans=min(ans,Min+dis(now,0)); return ; } for(int i=1;i<=n;i++){ if(vis[i]) continue; vis[i]=true; dfs(i,Min+dis(now,i),cnt+1); vis[i]=false; } } int main(){ int T; scanf("%d",&T); while(T--){ int r,c; scanf("%d%d",&r,&c); scanf("%d%d",&x[0],&y[0]); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]); dfs(0,0,0); printf("The shortest path has length %d\n",ans); } return 0; } E 方块涂色(贪心)

  思路:签到题,直接涂前 aaa 行和前 bbb 列,然后计算剩下没有涂色的即可。

#include using namespace std; int main(){ long long n,m,a,b; while(cin>>n>>m>>a>>b){ cout<<n*m-(a*m+b*n-a*b)<<endl; } return 0; } F 累乘数字(签到)

  思路:在 nnn 后面加 2d2d2d 个 000 即可,最近遇到大数比较多,没有思索直接就高精度乘单精度来计算了。

#include using namespace std; typedef long long ll; const int maxn=1e5+10; int ans[maxn]; int main(){ int n,d; while(~scanf("%d%d",&n,&d)){ int len=0; ans[0]=1; len=1; for(int i=0;i<len;i++) ans[i]*=n; for(int i=0;i<len;i++){ ans[i+1]+=ans[i]/10; ans[i]%=10; } while(ans[len]){ ans[len+1]+=ans[len]/10; ans[len]%=10; len++; } for(int q=1;q<=d;q++){ for(int i=0;i<len;i++) ans[i]*=100; for(int i=0;i=0;i--) printf("%d",ans[i]); puts(""); for(int i=0;i<len;i++) ans[i]=0; } return 0; } G 仓库选址(枚举)

  思路:由于数据范围比较小,直接枚举算出在每一个点的值,最后找到最小值就行了。

#include using namespace std; #define pb push_back typedef long long ll; const ll inf=0x3f3f3f3f3f3f3f; const int maxn=1e2+10; int a[maxn][maxn]; struct Node{ int x,y; Node(){} Node(int x,int y):x(x),y(y){} }; ll dis(Node node1,Node node2){ return abs(node1.x-node2.x)+abs(node1.y-node2.y); } int main(){ int T; scanf("%d",&T); while(T--){ ll ans=inf; int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++) scanf("%d",&a[i][j]); } for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ Node node=Node(i,j); ll res=0; for(int x=1;x<=m;x++){ for(int y=1;y<=n;y++){ res+=dis(node,Node(x,y))*a[x][y]; } } ans=min(ans,res); } } printf("%lld\n",ans); } return 0; } H 货物种类(差分)

  思路:分别用 vetorvetorvetor 记录某个区间放入了什么数据,l[i]l[i]l[i] r[i]r[i]r[i] 记录区间的头和尾放入的货物 ididid。visvisvis 用来表示编号为 iii 的物品的数量。遍历 [1,n][1,n][1,n] 用差分的方法来一次计算每个仓库放了多少种货物。

#include using namespace std; #define pb push_back const int maxn=1e5+10; vectorl[maxn],r[maxn]; mapvis; int main(){ int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int l1,r1,d; scanf("%d%d%d",&l1,&r1,&d); l[l1].pb(d); r[r1+1].pb(d); } int ans=-1,inx=-1,cnt=0; for(int i=1;i<=n;i++){ for(auto j:l[i]){ if(!vis[j]) cnt++;//当前货物没有数量为 0,货物需要加一种 vis[j]++;//该仓库当前货物数量 } for(auto j:r[i]){ vis[j]--;//该仓库当前货物数量 if(!vis[j]) cnt--;//当前货物没有了 } //cout<<cnt<<" "; if(ans<cnt){ ans=cnt; inx=i; } } //cout<<endl; printf("%d\n",inx); return 0; } J 计算A+B(大数加法)

  思路:此题换成了保证没有前导 000 的情况,所以直接分离出 AAA 和 BBB进行大数加法即可。多组数据,注意数组的清空问题。

#include using namespace std; typedef long long ll; const int maxn=1e5+10; char str[maxn],a[maxn],b[maxn]; int c[maxn],d[maxn],ans[2*maxn]; void cal(){ memset(c,0,sizeof(c)); memset(d,0,sizeof(d)); memset(ans,0,sizeof(ans)); int lena=strlen(a),lenb=strlen(b); for(int i=0;i<lena;i++) c[i]=a[lena-i-1]-'0'; for(int i=0;i<lenb;i++) d[i]=b[lenb-i-1]-'0'; int len=max(lena,lenb); for(int i=0;i9){ ans[i]-=10; ans[i+1]++; } } len=ans[len]?len+1:len; for(int i=len-1;i>=0;i--) printf("%d",ans[i]); puts(""); } int main(){ int T; scanf("%d",&T); while(T--){ memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); scanf("%s",str); int n=strlen(str),cnt1=0,cnt2=0; int inx=-1; for(int i=0;i<n;i++){ if(str[i]='0') a[cnt1++]=str[i]; if(str[i]=='+') { inx=i;break; } } if(inx==-1||inx==n-1||inx==0){ puts("skipped"); continue; } bool flag=true; for(int i=inx+1;i<n;i++){ if(str[i]='0') b[cnt2++]=str[i]; else { flag=false; break; } } //cout<<cnt1<<" "<<cnt2<<endl; if(flag){ //puts(a); puts(b); cal(); }else{ puts("skipped"); } } return 0; }
作者:Max_n



牛客

需要 登录 后方可回复, 如果你还没有账号请 注册新账号