9-1拼多多题目,4题AK

9-1拼多多题目,4题AK

需要笔试辅导的可以私我,ACM金牌退役选手,已拿腾讯和阿里offer,可以视频会议1V1辅导。

num1

题意:正方形划分为8个部分。
思路:直接判断就行。代码写得臭就不发了。

num2

题意:给定01矩阵,有一些连通的1,用0分割,现在你最多可以把其中1个1替换位置,问替换之后的最大连通块是多大。
思路:为了保证做法不会出错,我们得考虑:

  1. 如果只有一个连通块,那么它就是答案;
  2. 多个连通块(最多为4)是否可以移动内部的某块来连接;
  3. 多个连通块是否可以通过外部的某个1来连接。

对于2,3众情况,我们把他统一为,如果多个连通块中间只被一个空格隔开,那么答案就是这几个连通块大小之和。同时如果这几个连通块之外还有连通块,那么答案+1。+1是表示用外部的连通块来“”这个1.

综上,我的代码用并查集实现,这样可以得到每个连通块的编号、大小; 移动1,等效于枚举被填的那个位置,然后看4周会不会贡献,贡献并不是独立的,所以还得用并查集判重;最后判定是否+1;

----代码写得比较长,不要嫌弃----

#include<bits/stdc++.h>
using namespace std;
const int maxn=410;
int mp[maxn][maxn],fa[maxn*maxn];
int id[maxn][maxn],ans,num[maxn*maxn],cnt;
int tfa[maxn];
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
int find(int x)
{
    if(x==fa[x]) return x;
    return fa[x]=find(fa[x]);
}
void Merge(int x1,int y1,int x2,int y2)
{
    if(mp[x1][y1]&&mp[x2][y2]){
        int w=find(id[x1][y1]);
        int v=find(id[x2][y2]);
        if(w!=v) {
            num[v]+=num[w];
            ans=max(ans,num[v]);
            fa[w]=fa[v];
            cnt--;
        }
    }
}
void add(int i,int j,int &tmp,int &sum)
{
    int d=find(id[i][j]),F=1;
    for(int i=1;i<=tmp;i++){
        if(tfa[i]==d){
            F=0; break;
        }
    }
    if(!F) return ;
    tmp++;
    sum+=num[d];
    tfa[tmp]=d;
}
int main()
{
    int N,M;
    scanf("%d%d",&N,&M);
    for(int i=1;i<=N;i++){
        for(int j=1;j<=M;j++){
            scanf("%d",&mp[i][j]);
            id[i][j]=(i-1)*M+j;
            if(mp[i][j]) {
                num[id[i][j]]=1;
                ans=1;
                cnt++;
            }
            fa[id[i][j]]=id[i][j];
        }
    }
    for(int i=1;i<=N;i++){
        for(int j=1;j<=M;j++){
            if(i>1) Merge(i-1,j,i,j);
            if(j>1) Merge(i,j-1,i,j);
        }
    }
    if(cnt>2){
        for(int i=1;i<=N;i++){
            for(int j=1;j<=M;j++){
                if(mp[i][j]) continue;
                int tmp=0,sum=0;
                for(int k=0;k<4;k++){
                    int nowx=i+dx[k],nowy=j+dy[k];
                    if(nowx>=1&&nowx<=N&&nowy>=1&&nowy<=M){
                       if(mp[nowx][nowy]){
                           add(nowx,nowy,tmp,sum);
                       }
                    }
                }
                if(tmp==cnt) ans=max(ans,sum);
                else ans=max(ans,sum+1);
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

num3

题意:普通的01背包,但是现在体积可能为负数。
思路:一眼题,因为体积为负数,表示我们的体积会变,这种情况,我们把把变为相反数即可,表示我一开始就装进去,那么在跑背包的时候选择了它的相反数这个物体,表示把他移除。而这个时候所有的物体都是正他体积,跑01背包就行。
注:如果你不会01背包的话,那么你在学习的时候得注意,第二个for倒序遍历,这样防止重复更新答案。或者用二维的dp。

#include<bits/stdc++.h>
using namespace std;
const int maxn=410;
int c[maxn],v[maxn],ans;
int dp[40010];
int main()
{
    int N,M;
    scanf("%d%d",&N,&M);
    for(int i=1;i<=N;i++){
        scanf("%d%d",&c[i],&v[i]);
        if(c[i]<=0){   //负的物体取反
            ans+=v[i];
            M-=c[i];
            c[i]=-c[i];
            v[i]=-v[i];
        }
    }
    for(int i=1;i<=N;i++)  //01背包
        for(int j=M;j>=c[i];j--)
            dp[j]=max(dp[j],dp[j-c[i]]+v[i]);

    for(int i=0;i<=M;i++) {
            dp[M]=max(dp[M],dp[i]);
    }
    printf("%d\n",ans+dp[M]);
    return 0;
}

num4

位运算和gcd
容斥原理,求所有m的集合,在这个集合的所有数,求一下lcm(最小公倍数),如果|集合|是奇数,ans+=n/lcm,否则ans-=n/lcm 。

具体的:先从简单的问题走起,问1到10里面多少个2的倍数-------> ans=10/2=5;

    问1到10里面多少个5的倍数------->     ans=10/5=2;

    问1到10里面多少个2或者5的倍数------->     ans=10/5+10/2-10/10=6;

其实也就是容斥的一种特殊情况----抽屉原理。

所以这里用二进制枚举所有情况(对应1到F),二进制对应的1,表示选择、0表示不选择;然后把1对应的位(if(i&(1<<j)))求LCM;算贡献的时候取决于1的个数。

#include <bits/stdc++.h>
using namespace std;
#define LL long long
LL a[40];
int main(){
    LL N,M,ans=0,gd;
    scanf("%d%d",&N,&M);
    for(int i=1;i<=M;i++) {
        scanf("%d",&a[i-1]);
    }
    LL F=(1<<M)-1;
    for(int i=1;i<=F;i++){
        LL cnt=0;
        for(int j=0;j<M;j++){
            if(i&(1<<j)){
                cnt++;
                if(cnt==1) gd=a[j];
                else gd=gd*a[j]/(__gcd(a[j],gd));
            }
        }
        if(cnt&1){
            ans+=N/gd;
        }
        else ans-=N/gd;
    }
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/nimphy/article/details/108353321
9-1
今日推荐