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_ixi1≤i≤n1 \le i \le n1in,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;
}

 

 

posted @ 2022-01-26 15:34  su-yichen  阅读(55)  评论(0编辑  收藏  举报