首页 > 其他分享 >Living-Dream 系列笔记 第8期

Living-Dream 系列笔记 第8期

时间:2024-03-09 12:34:47浏览次数:25  
标签:Living min int double 31 笔记 ans Dream id

本期主要讲解的与上期相同。

例题

T1

上课的时候调这个题感觉要吐了 \(qwq\)。。。

首先读入 \(n\) 行字符串,可以采取忽略中间无关单词的方式来直接读取 \(X\) 和 \(Y\)。

将所有名字存入 \(a\) 数组,对 \(a\) 数组按字典序排序后就可以开始 \(\text{DFS}\) 了,这里建议使用 next_premutation

设计一个 check 函数来判定当前全排列是否满足 \(n\) 条限制。具体实现:

  • 遍历 \(n\) 条限制,对于第 \(i\) 条限制,在 \(8\) 个名字中找到对应的 \(X_i\) 和 \(Y_i\),保存它们的位置。

  • 判断它们位置的绝对差是否 \(=1\)(相邻)即可。

#include<bits/stdc++.h>
using namespace std;

int n;
string x[8],y[8];
string ans[8]={"Beatrice","Belinda","Bella","Bessie","Betsy","Blue","Buttercup","Sue"};

int getpos(string x){
	int p;
	for(int i=0;i<8;i++)
		if(ans[i]==x){
			p=i; break;
		}
	return p;
}
bool check(){
	for(int i=1;i<=n;i++){
		int p1=getpos(x[i]),p2=getpos(y[i]);
		if(abs(p1-p2)!=1) return 0;
	}
	return 1;
}

int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>x[i];
		for(int j=1;j<=5;j++)
			cin>>y[i];
	}
	
	do{
		if(check()){
			for(int i=0;i<8;i++) cout<<ans[i]<<'\n';
			break;
		}
	}while(next_permutation(ans,ans+8));
	
	return 0;
}

习题

T2

一个矩阵有主对角线(左上到右下)和副对角线(右上到左下),主对角线经过点的 \(x,y\) 坐标差一定,副对角线则是和一定。

于是我们可以记录三个 \(bool\) 数组 \(c,m,e\),分别记录在当前列 / 主对角线 / 副对角线是否能放置皇后。

在 \(\text{dfs(x)}\) 中我们定义行为格子,列为填入的数字,那么此题就变成了一个全排列问题。在 \(1 \sim n\) 遍历填入哪一列时,我们仅需判断 \(c_i,m_{x-i+n},e_{x_i}\) 是否均为 \(false\),若是则可以放置皇后。

注意回溯。

#include<bits/stdc++.h>
using namespace std;

int n,sum,ans[31];
int col[31],m[31],e[31];

void dfs(int x){
    if(x==n+1){
        sum++;
        if(sum<=3){
            for(int i=1;i<=n;i++) cout<<ans[i]<<' ';
            cout<<'\n';
        }
        return;
    }
    
    for(int i=1;i<=n;i++){
        if(!col[i]&&!m[x-i+n]&&!e[x+i]){
            col[i]=m[x-i+n]=e[x+i]=1;
            ans[x]=i;
            dfs(x+1);
            col[i]=m[x-i+n]=e[x+i]=0;
        }
    }
}

int main(){
    cin>>n;
    dfs(1);
    cout<<sum;
    return 0;
}

T3

考虑指数型枚举,即填格子时仅有填 / 不填两种选择,时间复杂度 \(O(2^n)\)。

在 \(\text{DFS}\) 函数中传入两个参数:\(x\) 和 \(tot\),分别记录即将填的格子数以及已经填完的格子数。

当 \(x=g+1\) 时,若符合要求且 \(tot <\) 全局答案,则更新全局答案并将当前选择方案 \(copy\) 给全局选择方案。

对于判断某一方案是否合法,则可以对于所有选择的种类,依次判断每一列之和是否 \(<\) 每头牛需要的维他命,若是则返回 \(1\);若均 \(\ge\) 所需维他命,则返回 \(1\)。

#include<bits/stdc++.h>
using namespace std;

int v,g,minn=1e9+31;
int ans[31],Ans[31];
int a[31],b[31][31];

bool check(int tot){
    for(int j=1;j<=v;j++){
        int sum=0;
        for(int i=1;i<=tot;i++) sum+=b[ans[i]][j];
        if(sum<a[j]) return 0;
    }
    return 1;
}

void dfs(int x,int tot){
    if(x==g+1){
        if(check(tot)){
            if(tot<minn){
                minn=tot;
                for(int i=1;i<=minn;i++) Ans[i]=ans[i];
            }
        }
        return;
    }

    ans[tot+1]=x;
    dfs(x+1,tot+1);
    
    dfs(x+1,tot);
}

int main(){
    cin>>v;
    for(int i=1;i<=v;i++) cin>>a[i];
    cin>>g;
    for(int i=1;i<=g;i++)
        for(int j=1;j<=v;j++)
            cin>>b[i][j];
    dfs(1,0);

    cout<<minn<<' ';
    for(int i=1;i<=minn;i++) cout<<Ans[i]<<' ';
    return 0;
}

T4

建立一个 \(b\) 数组保存下标,对 \(b\) 数组进行枚举全排列来遍历所有的顺序。

对于每一种顺序,遍历 \(n\) 个点,通过对上 / 下 / 左 / 右 / 离它最近的油的边界与它的距离取 \(\min\) 来得到在第 \(i\) 个点的最大半径,累加所有 \(n\) 格点的半径,用总面积减去就得到了剩余面积,对所有这样的剩余面积取 \(\min\) 即可。

注意精度问题。

#include<bits/stdc++.h>
using namespace std;

int n,ans=1e9+31;
double S,up,down,lft,rgt;
double x,y,xx,yy;
double rr[31];
struct node{
    int a,b;
}p[31];
int id[31];

double dist(int aa,int bb){
    return sqrt((p[aa].a-p[bb].a)*(p[aa].a-p[bb].a)+(p[aa].b-p[bb].b)*(p[aa].b-p[bb].b));
}
double surf(){
    double sum=0.0;
    for(int i=1;i<=n;i++){
        double u=up-p[id[i]].b,d=p[id[i]].b-down,l=p[id[i]].a-lft,r=rgt-p[id[i]].a;
        double t=1e9;
        for(int j=i-1;j>=1;j--)
            t=min(t,dist(id[i],id[j])-rr[j]);
        
        if(t<0){ rr[i]=0; continue; }
        rr[i]=min(u,min(d,min(l,min(r,t))));
        sum+=rr[i]*rr[i]*3.1415926;
    }
    return sum;
}

int main(){
    cin>>n;
    cin>>x>>y>>xx>>yy;
    for(int i=1;i<=n;i++){
        cin>>p[i].a>>p[i].b;
        id[i]=i;
    }
    up=max(y,yy),down=min(y,yy),lft=min(x,xx),rgt=max(x,xx);
    S=(up-down)*(rgt-lft);
    
    do{
        double sf=surf();
        ans=min(ans,(int)(round(S-sf)));
    }while(next_permutation(id+1,id+n+1));
    cout<<ans;
    return 0;
}

标签:Living,min,int,double,31,笔记,ans,Dream,id
From: https://www.cnblogs.com/XOF-0-0/p/18062520

相关文章

  • Living-Dream 系列笔记 第9期
    模拟赛掉大分(悲T1板子,不讲。T2首先很明显这题是个去重全排列。和模板的区别就是加了一个\(sum\)参数记录目前已经放了几个苹果。当\(x=n+1\)时若\(sum=m\),则更新答案。同时加入一个剪枝:若在搜索过程中\(sum>m\),则直接return结束搜索。#include<bits/stdc++.h>usi......
  • Living-Dream 系列笔记 第6期
    模拟赛。寄。T1对于每次询问,二分查找数组中对应值的原下标即可,因此需要用结构体存储原始数据和原始下标。这当然是比较麻烦的做法。另一种做法则是开一个map替代桶来存储数组中每个元素的下标,对于每个询问输出即可。另外值得注意的是,本题默认询问之间相互独立。时间复杂度......
  • Living-Dream 系列笔记 第7期
    本期主要讲解深度优先搜索\(\text{DFS}\)。知识点种类:全排列。可以想象为填格子。去重全排列,即组合。时间复杂度均为\(O(n!)\)。\(\text{DFS}\)题的特征:求方案总数/最值。数据范围极小(一般\(n\le20\))。无法直接暴力枚举(因为循环嵌套层数不确定)。......
  • Living-Dream 系列笔记 第4期
    本期主要讲解二分答案。知识点使用场景:最小值最大化,或最大值最小化。在限制条件下找最值。与二分查找的区别:L、R均为答案,而非下标。输出:最大化输出L,反之输出R。例题T1二分\(M\)的值,边界为\(L=-1,R=\max{\{a_i\}}\)。每次枚举到一个\(mid\)就对于每个......
  • Living-Dream 系列笔记 第5期
    本期主要讲解二分答案的进阶。例题T1二分需要的秒数,在check函数中对于每件衣服,若其在\(x\)秒内无法自然晒干,则使用烘干机,并令\(sum\)加上使用烘干机的秒数,最后判断\(sum\)是否\(\lex\)即可。\(Trick\):二分边界需要按数据范围尽可能开大,不能开小了。#include<bits/......
  • 挑选一款适合自己的笔记本电脑的步骤
    你知道如何挑选一款适合自己的笔记本电脑吗?笔记本电脑有许多品牌和型号,因此挑选出合适的笔记本电脑是一项艰巨的任务。为了能够找到最适合你的笔记本电脑,你需要考虑一系列因素。需要先了解几个常见问题:·从什么渠道购买笔记本·笔记本电脑品牌都有哪些·购买笔记本首先弄清......
  • 3/9 训练笔记
    P5268[SNOI2017]一个简单的询问题解不妨把每个区间表示成\(|V|\)维向量\(b\)的形式,其中\(b[i]\)为在区间\([l,r]\)中,\(i\)出现的次数。然后我们发现要求的实际上是\(a\cdotb\)。拆一下(这里用\(g(i)\)表示\([1,i]\)的向量):\(a\cdotb=[l_1,r_1]\cdot[l_......
  • 课堂笔记2
    define_CRT_SECURE_NO_WARNINGSinclude<stdio.h>//////冒泡排序该方法只能进行整数的排序//voidBubbleSort(intarr[],intsz)//{//inti=0;//intj=0;//for(i=0;i<sz-1;i++)//{//for(j=0;j<sz-1-i;j++)......
  • 王道计算机网络截图笔记
    目录第一章概述1.计算机网络概览1.1网络与计算机网络1.2计算机网络的功能1.3计算机网络的组成1.3.1组成部分1.3.2工作方式1.3.3功能组成1.4计算机网络的分类1.5小结2.计算机网络的标准化工作2.1标准的分类2.2RFC2.3标准化工作的相关组织2.4小结3.计算机网络性能指标3......
  • 2024.3.9 笔记
    2024.3.9笔记P1948题目大意为在无向图上求出从\(1\)到\(N\)的路径,使路径上第\(k+1\)大的边权尽量少。第一种是DP用\(f[i][j]\)表示从\(1\)到点\(i\),用了\(j\)条免费线的最小花费。对于一条\(u->v\)的边\(e\)有转移:不用免费线\(f_{v,k}=min(f_{v,k},max......