K-Goodness String
链接:https://codingcompetitions.withgoogle.com/kickstart/round/0000000000436140/000000000068cca3
题意:修改一个字符串里的字符,使得它进行回文对比时刚好相差为K,至少修改多少字符。
题解:直接进行对比,求出相异的格子数为M,则答案为abs(k-M)
#include<bits/stdc++.h>
using namespace std;
int T,len,k;
char s[210000];
int main(){
cin>>T;
for(int t=1;t<=T;t++){
cout<<"Case #"<<t<<": ";
cin>>len>>k;
cin>>(s+1);
int sum=0;
for(int i=1;i<=len/2;i++){
if(s[i]!=s[len-i+1])sum++;
}
cout<<abs(k-sum)<<endl;
}
}
L Shaped Plots
链接:https://codingcompetitions.withgoogle.com/kickstart/round/0000000000436140/000000000068c509
题意:给一个01矩阵,求有多少个L形状,要求为长边为短边的刚好两倍。
题解:统计每一个格子从四个方向延伸过来它总共有几个,
暴力枚举中间点,计算有多少L可以经过这个。
#include<bits/stdc++.h>
using namespace std;
const int N=1100;
int T,n,m;
int a[N][N],top[N][N],le[N][N],ri[N][N],bo[N][N],ans;
int cal(int x,int y){
if(x<2||y<2)return 0;
y=min(x/2,y);
return y-1;
}
int main(){
cin>>T;
for(int t=1;t<=T;t++){
cout<<"Case #"<<t<<": ";
cin>>n>>m;
for(int i=0;i<=n+1;i++){
for(int j=0;j<=m+1;j++){
a[i][j]=0;
top[i][j]=0;
le[i][j]=0;
ri[i][j]=0;
bo[i][j]=0;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i][j]==1)top[i][j]=top[i-1][j]+1;
else top[i][j]=0;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i][j]==1)le[i][j]=le[i][j-1]+1;
else le[i][j]=0;
}
}
for(int i=1;i<=n;i++){
for(int j=m;j>=1;j--){
if(a[i][j]==1)ri[i][j]=ri[i][j+1]+1;
else ri[i][j]=0;
}
}
for(int i=n;i>=1;i--){
for(int j=1;j<=m;j++){
if(a[i][j]==1)bo[i][j]=bo[i+1][j]+1;
else bo[i][j]=0;
}
}
ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i][j]==1){
ans+=cal(top[i][j],le[i][j]);
ans+=cal(top[i][j],ri[i][j]);
ans+=cal(le[i][j],top[i][j]);
ans+=cal(le[i][j],bo[i][j]);
ans+=cal(bo[i][j],le[i][j]);
ans+=cal(bo[i][j],ri[i][j]);
ans+=cal(ri[i][j],top[i][j]);
ans+=cal(ri[i][j],bo[i][j]);
}
}
}
cout<<ans<<endl;
}
return 0;
}
Rabbit House
链接:https://codingcompetitions.withgoogle.com/kickstart/round/0000000000436140/000000000068cb14
题意:一个矩阵,每个格子有相应高度,可以填高每个格子的高度,要使得相邻格子的高度差最多为1,问至少填多少高度。
题解:贪心算法,每次选最高的,然后检查四周,把不满足的填到高度-1,不断重复这个过程。可以用优先队列来做,每次选最高的即可。复杂度RClog(RC)。
继续优化,可以发现最高的高度为G,则其它所有格子高度至少为G-R-C+2,故可以把选最高的这个过程的优先队列继续优化,用桶来实现,每次选最高的,然后修改其它的,加入桶里的其它位置,直接一遍扫下来即可,复杂度RC。
#include<bits/stdc++.h>
using namespace std;
const int N=310;
struct node{
long long x,y,h;
bool operator <(const node &x)const{
return h<x.h;
}
};
long long a[N][N],flag[N][N],ans;
long long T,n,m,x,y;
long long dx[4]={-1,0,0,1};
long long dy[4]={0,-1,1,0};
priority_queue<node>q;
int main(){
cin>>T;
for(int t=1;t<=T;t++){
cout<<"Case #"<<t<<": ";
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
flag[i][j]=0;
cin>>a[i][j];
q.push((node){i,j,a[i][j]});
}
}
ans=0;
while(q.size()){
node now=q.top();
q.pop();
if(flag[now.x][now.y]==1)continue;
flag[now.x][now.y]=1;
x=now.x;
y=now.y;
for(int i=0;i<4;i++){
int xx=x+dx[i];
int yy=y+dy[i];
if(xx<1||xx>n||yy<1||yy>m)continue;
if(flag[xx][yy]==1)continue;
if(now.h-1>a[xx][yy]){
ans+=now.h-a[xx][yy]-1;
a[xx][yy]=now.h-1;
q.push((node){xx,yy,a[xx][yy]});
}
}
}
cout<<ans<<endl;
}
return 0;
}
Checksum
链接:https://codingcompetitions.withgoogle.com/kickstart/round/0000000000436140/000000000068c2c3
题意:一个N*N的01矩阵A[i][j],事先求出每行每列的异或值,现在中间有些格子被破坏了,还原这些格子需要B[i][j]的时间,在信息足够的情况下,格子可以直接通过异或值推理出来,问要想还原整个01矩阵,至少需要多少时间。
题解:建立行和列的二分图(上下两排),第i行第j列如果被破坏还原需要B[i][j]的代价,则上排第i个点向下排第j个点连一条边权为B[i][j]的边,除非图变成一棵树或者森林,那么之后就可以通过自我推理推出所有点,否则信息就不够无法还原,目标是砍掉尽可能少的边权和,使剩下的变成一个树或者森林,反过来也就是希望剩下的树的边权最大,则问题变成求最大生成树,总和减去最大生成树权值即是答案。
#include<bits/stdc++.h>
using namespace std;
const int N=510;
int a[N][N],b[N][N];
int T,n,ans,yes,x;
struct arr{
int x,y,v;
}e[260000];
int cmp(arr a,arr b){
return a.v>b.v;
}
int fa[N*2];
int getfa(int x){
if(fa[x]==x)return x;
return fa[x]=getfa(fa[x]);
}
int main(){
cin>>T;
for(int t=1;t<=T;t++){
cout<<"Case #"<<t<<": ";
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>a[i][j];
}
}
int sum=0;
int m=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>x;
if(x==0)continue;
m++;
e[m].x=i;
e[m].y=n+j;
e[m].v=x;
sum+=x;
}
}
for(int i=1;i<=n;i++)cin>>x;
for(int i=1;i<=n;i++)cin>>x;
for(int i=1;i<=n*2;i++)fa[i]=i;
sort(e+1,e+m+1,cmp);
int maxsum=0;
for(int i=1;i<=m;i++){
int fa1=getfa(e[i].x);
int fa2=getfa(e[i].y);
if(fa1!=fa2){
fa[fa2]=fa1;
maxsum+=e[i].v;
}
}
cout<<sum-maxsum<<endl;
}
return 0;
}