PAT 甲级 2018年秋季

本文介绍了三个算法题目,包括狼人杀逻辑判断、危险品不能同包的判断以及旅行商问题的解决。通过狼人杀的逻辑判断函数,确定狼人和村民的位置;危险品包装问题中,检查是否存在能同时装箱的危险品组合;旅行商问题则通过最短路径算法找出最短的旅行路线。这些题目涉及逻辑推理、图论和最优化算法。
摘要由CSDN通过智能技术生成

1 PAT 甲级 1148 Werewolf - Simple Version

#include <bits/stdc++.h>
using namespace std;
struct Msg{
    int type,id;
};
int n;Msg msg[110];
int is_wolf[110];
bool IsValid(int l1,int l2,int w){
    // l1 是狼,l2 是村民,w 是没说谎的狼 
    if(l2==w) return false;
    if(l2==l1) return false;
    memset(is_wolf,0,sizeof(is_wolf));
    for(int i=1;i<=n;++i){
        int id=msg[i].id,type=msg[i].type;
        if(i!=l1&&i!=l2){
            if(is_wolf[id]==0) is_wolf[id]=type;
            else if(is_wolf[id]!=type) return false;
        }else{
            if(is_wolf[id]==0) is_wolf[id]=-type;
            else if(is_wolf[id]!=-type) return false;
        }
    }
    int ctr=0;
    for(int i=1;i<=n;++i){
        if(is_wolf[i]==-1){
            if(i!=l1&&i!=w) return false;
            ++ctr;
        }
    }
    if(ctr>2) return false;
    if(is_wolf[l1]==1||is_wolf[w]==1) return false;
    return true;
}
bool Judge(int w1,int w2)
{
    // 循环第二个说谎的人 
    for(int i=1;i<=n;++i){
        if(IsValid(w1,i,w2)) return true;
        if(IsValid(w2,i,w1)) return true;
    }
    return false;
}

int main(){
    cin>>n;cin.get();
    for(int i=1;i<=n;++i){
        char tmp;int id;
        cin>>tmp>>id;cin.get();
        msg[i].type=(tmp=='+'?1:-1);
        msg[i].id=id;
    }
    for(int i=1;i<=n;++i){
        for(int j=i+1;j<=n;++j){
            if(Judge(i,j)){
                cout<<i<<" "<<j;
                goto fin;
            }
        }
    }
    cout<<"No Solution";
    fin: return 0;
}

2 PAT 甲级 1149 Dangerous Goods Packaging

#include <bits/stdc++.h>
using namespace std;
set<int> no_comp[100010];
int main(){
    int n,m;cin>>n>>m;
    for(int i=0;i<n;++i){
        int a,b;cin>>a>>b;
        no_comp[a].insert(b);
        no_comp[b].insert(a);
    }
    for(int i=0;i<m;++i){
        int k;cin>>k;bool yes=true;
        vector<int> item(k);
        for(int j=0;j<k;++j) cin>>item[j];
        for(int p1=0;p1<k;++p1){
            for(int p2=p1+1;p2<k;++p2){
                if(no_comp[item[p1]].count(item[p2])!=0) {yes=false;goto fin;}
            }
        }
        fin:
        if(yes) printf("Yes\n");
        else printf("No\n");
    }
}

3 PAT 甲级 1150 Travelling Salesman Problem

#include <bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=210;
int graph[N][N];
int vis[210];
int main(){
    for(int i=0;i<N;++i){
        for(int j=0;j<N;++j){
            graph[i][j]=INF;
        }
    }
    int n,m;cin>>n>>m;
    for(int i=0;i<m;++i){
        int x,y,dis;cin>>x>>y>>dis;
        graph[x][y]=graph[y][x]=dis;
    }
    int q;cin>>q;
    int min_dis=INF,ans=1;
    for(int i=0;i<q;++i){
        memset(vis,0,sizeof(vis));
        bool is_simple=true,is_cyc=true;
        
        int k;cin>>k;
        int dis=0,pre,now,beg;
        cin>>beg;pre=beg;vis[beg]++;
        for(int j=1;j<k;++j){
            cin>>now;
            dis=(graph[pre][now]!=INF?dis+graph[pre][now]:INF);
            pre=now;
            if(dis==INF) is_cyc=false;
            if(j!=k-1) vis[now]++;
            if(j==k-1&&now!=beg) is_cyc=false;
            if(vis[now]>1) is_simple=false;
        }
        for(int j=1;j<=n;++j) if(vis[j]==0) is_cyc=false;
        
        if(is_cyc&&dis<min_dis) min_dis=dis,ans=i+1;
        printf("Path %d: ",i+1);
        if(dis>=INF) printf("NA ");
        else printf("%d ",dis);
        if(!is_cyc) printf("(Not a TS cycle)\n");
        else if(is_simple) printf("(TS simple cycle)\n");
        else printf("(TS cycle)\n");
    }
    printf("Shortest Dist(%d) = %d",ans,min_dis);
}

4 PAT 甲级 1151 LCA in a Binary Tree

测试点2,根节点是根节点的祖先。

#include <bits/stdc++.h>
using namespace std;
const int MAXN=10010;
unordered_map<int,int> mp;
int val[MAXN];
int pre[MAXN],in[MAXN];
int lchild[MAXN],rchild[MAXN],father[MAXN],depth[MAXN];
int Build(int l1,int r1,int l2,int r2){
    if(l1>r1) return -1;
    int root=pre[l1];
    int idx=l2;
    while(idx<=r2&&in[idx]!=root) ++idx;
    lchild[root]=Build(l1+1,l1+idx-l2,l2,idx-1);
    rchild[root]=Build(l1+idx-l2+1,r1,idx+1,r2);
    return root;
}
void BFS(int root){
    if(root==-1) return;
    queue<int> q;
    q.push(root);
    depth[root]=1;father[root]=root;
    while(!q.empty()){
        int now=q.front();q.pop();
        if(lchild[now]!=-1){
            depth[lchild[now]]=depth[now]+1;
            father[lchild[now]]=now;
            q.push(lchild[now]);
        }
        if(rchild[now]!=-1){
            depth[rchild[now]]=depth[now]+1;
            father[rchild[now]]=now;
            q.push(rchild[now]);
        }
    }
}
int main(){
    int m,n;cin>>m>>n;
    for(int i=0;i<n;++i){
        int tmp;cin>>tmp;
        mp[tmp]=i;val[i]=tmp;
        in[i]=i;
    }
    for(int i=0;i<n;++i){
        int tmp;cin>>tmp;
        pre[i]=mp[tmp];
    }
    int root=Build(0,n-1,0,n-1);
    BFS(root);
    for(int i=0;i<m;++i){
        int u,v;cin>>u>>v;
        if(mp.count(u)==0&&mp.count(v)==0)
            printf("ERROR: %d and %d are not found.\n",u,v);
        else if(mp.count(u)==0)
            printf("ERROR: %d is not found.\n",u);
        else if(mp.count(v)==0)
            printf("ERROR: %d is not found.\n",v);
        else{
            if(u==v&&u!=val[root])
                printf("LCA of %d and %d is %d.\n",u,v,val[father[mp[u]]]);
            else{
                int a=mp[u],b=mp[v];
                while(depth[a]<depth[b]) b=father[b];
                while(depth[b]<depth[a]) a=father[a];
                while(a!=b) a=father[a],b=father[b];
                if(a==mp[u])
                    printf("%d is an ancestor of %d.\n",u,v);
                else if(a==mp[v])
                    printf("%d is an ancestor of %d.\n",v,u);
                else
                    printf("LCA of %d and %d is %d.\n",u,v,val[a]);
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值