1.25所有题总结

车厢调度的两种方法:1.依次判断是否是上个元素-1或比上个元素大,若不是则输出no

2.寻找不一定连续的(大,中,小)结构。

#include<bits/stdc++.h>
#define enter printf("\n")
#define n_times_a scanf("%d",&n);for(int i = 1;i <= n;i++){scanf("%d",&a[i]);}
using namespace std;
int main(){
    int n,a[200] = {},b[200];
    int top = 1,f = 1;
    scanf("%d",&n);
    for(int i = 1;i <= n;i++){
        scanf("%d",&a[i]);
    }
    for(int i = 1;i <= n;i++){
        //way#1
        /*//printf("%d , %d\n",a[i],top - 1);
        if(a[i] < top - 1){
            
            f = 0;
            break;
        }
        else top = a[i];*/  
        //way#2 
        // /* 
        if(a[i] == b[top]){
            b[top--] = 0;
            continue; //若为当前栈顶元素,则出栈 
        }
        for(int j = 1;j < top;j++){
            if(a[i] = b[j]){
                printf("NO");
                exit(0);
            }
        }
        for(int j = i==0?1:a[i-1]+1;j < a[i];j++){
            b[top++] = j;
        }
        // */
    }
    /*if(f)*/ printf("YES");
    //else printf("NO");
    return 0;
}

用进出栈来模拟进出站

2.迷宫问题

比较有进步的是学会了用数组记录行动规则,同时根据行动的显性+隐性规则进行模拟!

隐藏规则:不能原地不动,不能越界

题中注释较为详细

#include<bits/stdc++.h>
using namespace std;
int n,tot,a[10][10]; //地图 
int stp[3] = {-1,0,1};
int r[10][10]; //路线图 
void step(int x,int y){
    //printf("%d %d\n",y,x);
    if(y == 1 && x == n){
        //printf("ok\n");
        tot++;
        return;
    }
    for(int i = 0;i <= 2;i++){
        for(int j = 0;j <= 2;j++){
            if(stp[i] == 0 && stp[j] == 0) continue;  //不能原地不动 
            if(x+stp[i] > n||y+stp[j] > n||x+stp[i] < 1||y+stp[j] < 1) continue; //不能越界 
            if(a[y+stp[j]][x+stp[i]] == 1) continue;  //不能进入不可通过区域 
            if(r[y+stp[j]][x+stp[i]] == 1) continue; //路线不能重复 
            r[y+stp[j]][x+stp[i]] = 1;            
            step(x+stp[i],y+stp[j]);
            r[y+stp[j]][x+stp[i]] = 0;    
        }
    }
    
}
void input(){
    for(int i = 1;i <= n;i++){
        for(int j = 1;j <= n;j++){
            scanf("%d",&a[i][j]);
        }
    }
}
int main(){
    scanf("%d",&n);
    input();
    r[1][1] = 1;
    step(1,1);
    printf("%d",tot);
    return 0;
}
/*
3
0 0 0 
0 1 1
1 0 0 
*/

3.部落卫队问题

一道意料之外卡了很久的题,一开始的算法有漏洞:回溯的时候保持回溯前的仇敌状态,这个需要加减实现而不是0,1的区别!

同时判断过程复杂也使得思维紊乱,后面我都改成了函数形式

#include<bits/stdc++.h>
using namespace std;
int n,m,ans = 0,a[200]; 
int h[200][200]; //h表示仇敌关系, h[k][j]表示 k第j仇敌编号 
int op[200];    //记录选入的成员编号 
int b[200]; //0表示可选,1以上表示不可选 
int c[200];
void ck(int t){
    if(t > ans){
        ans = t;
        for(int i = 1;i <= n;i++){
            op[i] = a[i];
        }
    }
}
void ene(int i){
    int j = 1;
    while(h[i][j]){
        b[h[i][j]]++;
        j++;
    }
    b[i]++;
}
void abene(int i){
    int j = 1;
    while(h[i][j]){
        b[h[i][j]]--;
        j++;
    }
    b[i]--;
}
void prt(int t){
    printf("%d\n",t);
    for(int i = 1;i <= n;i++){
        printf("%d ",a[i]);
    }
    printf("\n");
}
void search(int t,int d){ //当前选入第几个人 ,从谁开始选     
    for(int i = d;i <= n;i++){    
        if(!b[i]){  //如果可选 
            ene(i);
            a[i] = 1;
            ck(t);
            //prt(t);
            search(t+1,i+1);
            a[i] = 0;
            abene(i);
        }
    }
}
void print(){
    //printf("answer:\n");
    printf("%d\n",ans);
    for(int i = 1;i <= n;i++){
        printf("%d ",op[i]);
    }
}
int main(){
    int k,x;
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= m;i++){
        scanf("%d %d",&k,&x);
        int l = 1;
        while(h[k][l] > 0) l++;
        h[k][l] = x;  
    }
    search(1,1);
    print();
    return 0;
}
/*
7 10
1 2
1 4
2 4
2 3
2 5
2 6
3 5
3 6
4 5
5 6
*/

4.最佳调度问题

题解似乎也过不了的一道题,时间复杂度还是要继续优化,

(以下是当前优化到的状态,还不知要试多久)

#include<bits/stdc++.h>
using namespace std; 
int mint,a[30],n,k;
int t[20];  //t[i]是第i个机器用时 
void dfs(int y,int r){  //已安排的任务数 最短用时(排序) 
    if(r >= mint){
        return;
    }
    if(y > n){
        if(r < mint) mint = r;
        return;
    }    
    for(int i = 1;i <= k;i++){
        t[i] = a[y]+t[i];
        dfs(y+1,max(r,t[i]));
        t[i] = t[i]-a[y];
    }
}
int main(){
    scanf("%d %d",&n,&k);
    for(int i = 1;i <= n;i++){
        scanf("%d",&a[i]);
    }
    mint = INT_MAX;
    dfs(1,0);
    printf("%d",mint);
}
//7 3 2 14 4 16 6 5 3

5.m着色问题

此题涉及知识盲区,纸上瞎写一通,看完题解也是一脸问号,目前只知道数组记录互相影响节点的算法

 

#include<bits/stdc++.h>
#define i i
using namespace std;
int n,m,k,e[10000],t[10000],a[10000];
int color[10000],tot;
void dfs(int x){ //着色点个数 
     if(x > n){
         tot++;
         return;
     }
     int i;
     bool b[1000] = {};
     i = color[x];
     while(i!=0){
         if(e[i]<x) b[a[e[i]]] = false;
         i = next[i];
     }
     for(int i = 1;i < k;i++){
         if(b[i]){
             a[x] = i;
             dfs(x+1);
         }
     }
    
}
int main(){
    cin>>n>>k>>m;
    int x,y;
    for(int i = 1;i <= k;i++){
        cin>>x>>y;
        if(x>y) swap(x,y);
        t[i] = e[x];t[i+k] = e[y];
        color[x] = i;color[y] = i+k;
        e[i] = y;e[i+k] = x;
    }
    tot = 0;
    dfs(1);
    cout<<tot<<endl;
}

 

posted @ 2022-01-25 16:00  yinfelix  阅读(43)  评论(0)    收藏  举报