2022寒假集训day4
day4(day5补完的)
继续刷搜索方面的题,
初步了解了序列。
T1
迷宫问题
题目描述
设有一个 n*n 方格的迷宫,入口和出口分别在左上角和右上角。迷宫格子中分别放 0 和 1 ,0 表示可通,1 表示不能,入口和出口处肯定是 0。迷宫走的规则如下所示:即从某点开始,有八个方向可走,前进方格中数字为 0 时表示可通过,为 1 时表示不可通过,要另找路径。找出所有从入口(左上角)到出口(右上角)的路径(不能重复),输出路径总数,如果无法到达,则输出 0。
输入格式
共 n+1 行;第一行位正整数 n,表示迷宫的行数及列数;接下来 n 行,每行 n 个数,表示对应的格子是否可以通过。
输出格式
路径总数。
输入样例
3
0 0 0
0 1 1
1 0 0
输出样例
2
提示说明
【数据说明】
100%数据满足:2<=n<10。
#include <bits/stdc++.h> using namespace std; int a[15][15]; int n; int X[15]={-1,1,0,0,-1,-1,1,1}; int Y[15]={0,0,-1,1,-1,1,-1,1}; int sum=0; void dfs(int x,int y) { if(x==1&&y==n) { sum++; return ; } for(int i=0;i<=7;i++) { int nx=x+X[i],ny=y+Y[i]; if(nx>0&&nx<=n&&ny>0&&ny<=n) if(a[nx][ny]==0) { a[nx][ny]=1;//biaoji dfs(nx,ny); a[nx][ny]=0; } } } int main(){ cin>>n; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ cin>>a[i][j]; } } a[1][1]=1; dfs(1,1); cout<<sum; return 0; }
还是深搜,一开始我用search没写出来QaQ。
除了判断八个方向上各是0或1,还要判断会不会越界。
if(nx>0&&nx<=n&&ny>0&&ny<=n) if(a[nx][ny]==0) { a[nx][ny]=1;//biaoji dfs(nx,ny); a[nx][ny]=0;
就是这个↑
————————————————————————————————————————
T2
部落卫队 洛谷P1692
题目描述
原始部落 byteland 中的居民们为了争夺有限的资源,经常发生冲突。几乎每个居民都有他的仇敌。部落酋长为了组织一支保卫部落的队伍,希望从部落的居民中选出最多的居民入伍,并保证队伍中任何 222 个人都不是仇敌。
给定 byteland 部落中居民间的仇敌关系,编程计算组成部落卫队的最佳方案。若有多种方案可行,输出字典序最大的方案。
输入格式
第 111 行有 222 个正整数 nnn 和 mmm,表示 byteland 部落中有 nnn 个居民,居民间有 mmm 个仇敌关系。居民编号为 1,2,⋯ ,n1,2, \cdots ,n1,2,⋯,n。接下来的 mmm 行中,每行有 222 个正整数 uuu 和 vvv,表示居民 uuu 与居民 vvv 是仇敌。
输出格式
第 111 行是部落卫队的人数;文件的第 222 行是卫队组成 xix_ixi,1≤i≤n1 \le i \le n1≤i≤n,xi=0x_i=0xi=0 表示居民 iii 不在卫队中,xi=1x_i=1xi=1 表示居民 iii 在卫队中。
#include <bits/stdc++.h> using namespace std; int v[10000],p[10000],sum,m; struct c{ int b[1000],k; }a[1000]; void dfs(int i,int s){ if(i==m+1){ if(s>sum){ memcpy(p,v,sizeof(v)); sum=s; } return; } if(!v[i]){ v[i]=1; for(int j=0;j<a[i].k;j++) v[a[i].b[j]]+=2; dfs(i+1,s+1); v[i]=0; for(int j=0;j<a[i].k;j++) v[a[i].b[j]]-=2; } dfs(i+1,s); } int main() { int n,x,y,i; cin>>m>>n; for(i=1;i<=n;a[x].b[a[x].k++]=y,i++) cin>>x>>y; dfs(1,0); printf("%d\n",sum); for(i=1;i<=m;i++) if(p[i]==1) printf("1 "); else printf("0 "); }
一开始读题时很模糊,如果一个人与多个人都有仇该如何判断,是不是也可能放在队伍里。
花费很长时间,T1 T2差了三个小时。
————————————————————————————————————————
T3
最佳调度问题
题目
假设有n(n<=20)个任务由k(k<=20)个可并行工作的机器完成。完成任务i需要的时间为ti。 试设计一个算法,对任意给定的整数n和k,以及完成任务i 需要的时间为ti ,i=1~n。计算完成这n个任务的最佳调度,使得完成全部任务的时间最早。
输入格式:
输入数据的第一行有2 个正整数n和k。第2 行的n个正整数是完成n个任务需要的时间。
输出格式:
将计算出的完成全部任务的最早时间输出到屏幕。
#include <bits/stdc++.h> using namespace std; int a[105],s[1005]; int n,k,result; int max(int x,int y){ if(x>y) return x; else return y; } void search(int x,int y) { int i if(y>=result) return; if(x>n) { if(y<result) result=y; return; } for(int i=1; i<=k; i++) { s[i]=s[i]+a[x]; search(x+1,max(y,s[i])); s[i]=s[i]-a[x]; } }int main() { cin>>n>>k; for(int i=1; i<=n; i++) cin>>a[i]; memset(s,0,sizeof(s)); result=INT_MAX; search(1,0); cout<<result; return 0; }
这道题主要就离谱在不管用什么方法,系统就是判断是超时,就是73分
————————————————————————————————————————
T4
图M的着色问题 洛谷P2819
题目背景
给定无向连通图G和m种不同的颜色。用这些颜色为图G的各顶点着色,每个顶点着一种颜色。如果有一种着色法使G中每条边的2个顶点着不同颜色,则称这个图是m可着色的。图的m着色问题是对于给定图G和m种颜色,找出所有不同的着色法。
题目描述
对于给定的无向连通图G和m种不同的颜色,编程计算图的所有不同的着色法。
输入格式
第1行有3个正整数n,k 和m,表示给定的图G有n个顶点和k条边,m种颜色。顶点编号为1,2,…,n。接下来的k行中,每行有2个正整数u,v,表示图G 的一条边(u,v)。
输出格式
程序运行结束时,将计算出的不同的着色方案数输出。
#include <bits/stdc++.h> using namespace std; int n,m,k,s,ks[10000]; int c[10000],e[10000],a[1000]; void search(int x){ if(x>n){ s++; return; } int i; bool b[1000]; i=ks[x]; memset(b,1,sizeof(b)); while(i!=0){ if(e[i]<x) b[a[e[i]]]=false; i=c[i]; } for(int i=1;i<=k;i++) if(b[i]){ a[x]=i; search(x+1); } } int main(){ cin>>n>>m>>k; int i,x,y; for(i=1;i<=m;i++){ cin>>x>>y; c[i]=ks[x]; ks[x]=i; e[i+m]=y; c[i+m]=ks[y]; ks[y]=i+m; e[i+m]=x; } s=0; search(1); cout<<s<<endl; return 0; }