0316南京理工大学机试模拟考(三)

contest地址:https://www.luogu.com.cn/contest/27549
节选了CE两个题(一二两题较简单,KMP没看)

题一

P1219 [USACO1.5]八皇后 Checker Challenge
八皇后问题
代码来源
考点:dfs,回溯
方法一:
利用三个数组b,c,d分别表示下标代表的列,主对角线、副对角线是否已经使用

#include <bits/stdc++.h>
using namespace std;
int a[10000],sum=0;
bool b[10000],c[10000],d[10000];
int n;
void dfs(int);
int print();
int main(){
	cin>>n;
	dfs(1);
	cout<<sum<<endl;
}
void dfs(int step){
	if(step>n){
		print();
		return;
	}
	else{
		for(int i=1;i<=n;i++){
		if((!b[i])&&(!c[step+i])&&(!d[step-i+n])){
			a[step]=i;
			b[i]=1;
			c[step+i]=1;
			d[step-i+n]=1;
			dfs(step+1);
			b[i]=0;
			c[step+i]=0;
			d[step-i+n]=0;
		    }
	    }
	}
}
int print(){
	if(sum<=2){
		for(int i=1;i<=n;i++){
			cout<<a[i]<<" ";
		}
		cout<<endl;
	}
	sum++;
}

方法二:
行坐标差的绝对值与列坐标差的绝对值比较,相同则在同对角线或同副对角线,舍去

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int n;
int a[20];
int visited[20];
int count=0;
void dfs(int step){
    int i,j,flag;
    if(step==n+1){
        count++;
        if(count<=3){
            for(i=1;i<=n;i++)
                printf("%d ",a[i]);
            printf("\n");
        }
        return;
    }
    for(i=1;i<=n;i++){
        if(visited[i]==0){
            flag=0;
            for(j=1;j<step;j++)
                if(abs(a[j]-i)==abs(j-step)){
                    flag=1;
                    break;
                }
            if(flag==0){
                a[step]=i;
                visited[i]=1;
                dfs(step+1);
                visited[i]=0;
            }
        }
    }
}
int main(){
    memset(visited,0,sizeof(visited));
    scanf("%d",&n);
    dfs(1);
    printf("%d\n",count);
    return 0;
}

题二

5. P2121 拆地毯=========很经典的一个题
地址:https://www.luogu.com.cn/problem/P2121
考点:最小生成树(kruskal)、并查集、图论
代码来源

#include <iostream>
#include <algorithm>
#define maxn 100005
using namespace std;
struct Edge{
    int u,v,w;
} edge[maxn];
int n,m,k,fa[maxn],cnt,ans;
int find(int x)
{
    if(fa[x]==x)
        return x;
    return fa[x]=find(fa[x]);
}
bool cmp(Edge a,Edge b)
{
    return a.w>b.w;
}
void kruskal()
{
    sort(edge+1,edge+m+1,cmp);
    for(int i=1;i<=m;i++)
    {
        int eu=find(edge[i].u);
        int ev=find(edge[i].v);
        if(eu==ev) continue;
        fa[eu]=ev;
        ans+=edge[i].w;
        cnt++;
        if(cnt==k) break;
    }
}
int main()
{
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++)
        fa[i]=i;
    for(int i=1;i<=m;i++)
        cin>>edge[i].u>>edge[i].v>>edge[i].w;
    kruskal();
    cout<<ans;
    return 0;
}

版权声明:本文为qq_43467414原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。