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版权协议,转载请附上原文出处链接和本声明。