ACdream区域赛指导赛之手速赛系列(6) 解题报告

A - Problem A

        题意:给一个完成的数独,判是否合法。。这个数独有9*9,25*25,36*36三种类型。

        思路:暴力。依次检查横向,纵向,n*n小正方形中是否合法。


#include <iostream>       
#include <stdio.h>       
#include <cmath>       
#include <algorithm>       
#include <iomanip>       
#include <cstdlib>       
#include <string>       
#include <memory.h>       
#include <vector>       
#include <queue>       
#include <stack>       
#include <map>     
#include <set>     
#include <ctype.h>       
#define INF 1000000010   
#define ll long long   
#define max3(a,b,c) max(a,max(b,c))   
#define MAXN 100010  
 
using namespace std;
 
int num[40][40];
bool cnt[1001];
 
 
 
int main(){
    int t;
    cin>>t;
    int _case=0;
    while(t--){
        _case++;
        int n;
        cin>>n;
        int N=n*n;
        bool valid=true;
        for(int i=1;i<=N;i++){
            memset(cnt,0,sizeof(cnt));
            for(int j=1;j<=N;j++){
                scanf("%d",&num[i][j]);
                cnt[num[i][j]]++;
            }
            for(int j=1;j<=N;j++){
                if(cnt[j]!=1)valid=false;
            }
        }
         
        for(int i=1;i<=N;i++){
            memset(cnt,0,sizeof(cnt));
            for(int j=1;j<=N;j++){
                cnt[num[j][i]]++;
            }
            for(int j=1;j<=N;j++){
                if(cnt[j]!=1)valid=false;
            }
        }
         
        if(!valid){
            printf("Case #%d: ",_case);
            cout<<"No"<<endl;
            continue;
        }
         
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                memset(cnt,0,sizeof(cnt));
                for(int k=1;k<=n;k++){
                    for(int l=1;l<=n;l++){
                        cnt[ num[i*n+k][j*n+l] ]++;
                    }
                }
                for(int j=1;j<=N;j++){
                    if(cnt[j]!=1)valid=false;
                }
                     
            }
        }
        if(valid){
            printf("Case #%d: ",_case);
            cout<<"Yes"<<endl;
        }else{
            printf("Case #%d: ",_case);
            cout<<"No"<<endl;
        }
    }
     
    return 0;
}


B - Problem B

        这题是学弟A的,丢个链接。

http://blog.csdn.net/u011639256/article/details/38930481

C - Problem C

         这题是学弟A的,丢个链接。

http://blog.csdn.net/u011639256/article/details/38930579

D - Problem D

        题意:最短路。n(n<=80000)个点,每个点有自己的颜色,同色点之间可以瞬移。然后有m条普通的有向边。给出S个询问,对每个询问回答点对间最短路。

        思路:点太多,实际上可以把同色的点看成是一个点。总点数最多有(26+10)^2个,用哈希函数把同色点缩成一点,建边时按缩点后建。然后用SPFA求最短路,因为不是每两个点之间都需要求解,用SPFA就比Floyd要好。


#include <iostream>       
#include <stdio.h>       
#include <cmath>       
#include <algorithm>       
#include <iomanip>       
#include <cstdlib>       
#include <string>       
#include <memory.h>       
#include <vector>       
#include <queue>       
#include <stack>       
#include <map>     
#include <set>     
#include <ctype.h>       
#define INF 1000000010   
#define ll long long   
#define max3(a,b,c) max(a,max(b,c))   
#define MAXN 100010  
 
using namespace std;
 
inline int chartoint(char c){
    if(c>='0'&&c<='9'){
        return c-'0'+1;
    }else{
        return c-'a'+11;
    }
}
 
inline int hash(string str){
    if(str.size()==1){
        return chartoint(str[0])*37;
    }else{
        return chartoint(str[0])*37+chartoint(str[1]);
    }
}
 
string name[80010];
 
struct Node{
    int v;
    int w;
}node;
 
vector<Node> E[1370];//[1370];
int ans[1370];
 
int main(){
    int t;
    cin>>t;
    int cs=0;
    while(t--){
         
        for(int i=0;i<1370;i++){
            E[i].clear();
        }
        cs++;
        int n;
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>name[i];
        }
        int m;
        cin>>m;
        for(int i=1;i<=m;i++){
            int u,v,w;
            cin>>u>>v>>w;
             
            Node no; no.v=hash(name[v]); no.w=w;
            E[hash(name[u])].push_back(no);
        }
         
        int S;
        cin>>S;
         
        printf("Case #%d:\n",cs);
        for(int k=1;k<=S;k++){
            int s,t;
            cin>>s>>t;
            s=hash(name[s]);
            t=hash(name[t]);
            for(int i=0;i<1370;i++)ans[i]=INF;
            ans[s]=0;
             
            queue<int> que;
            que.push(s);
            while(!que.empty()){
                int cur=que.front();que.pop();
                int siz=E[cur].size();
                for(int i=0;i<siz;i++){
                    if(ans[E[cur][i].v]>ans[cur]+E[cur][i].w ){
                        ans[E[cur][i].v]=ans[cur]+E[cur][i].w;
                        que.push(E[cur][i].v);
                         
                    }
                }
            }
            if(ans[t]==INF){
                cout<<"-1"<<endl;
            }else{
                cout<<ans[t]<<endl;
            }
        }
    }
    return 0;
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值