2015.12 hdu 校赛简易题解

01 The Country List

暴力for过去。

02 Polygon

计算几何模板。

03 The collector’s puzzle

因为盒子能使用多次,排序后取一个最接近的。

#include <bits/stdc++.h>

using namespace std;

#define ll long long 

int a[100010];
int b[100010];

int min3(int a,int b,int c){
    if(a<b){
        if(a<c)return a;
        return c;
    }else{
        if(b<c)return b;
        return c;
    }
}

int main(){
    int n,m;
    while(cin>>n>>m){
        
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        for(int i=1;i<=m;i++){
            scanf("%d",&b[i]);
        }
        
        sort(a+1,a+n+1);
        sort(b+1,b+m+1);
        b[0]=-1e9;    b[m+1]=1e9;    b[m+2]=1e9;
        
        int pos = 1;
        int ans = 0;
        for(int i=1;i<=n;i++){
            while(b[pos]<a[i] && pos<=m){
                pos++;
            }
            ans+=min3(abs(a[i]-b[pos-1]),abs(a[i]-b[pos]),abs(a[i]-b[pos+1]));
        }
        cout<<ans<<endl;
    }
    return 0;
}

04 Happy Value

最大生成树,拿MST改改就好。

05 Bitwise Equations

贪心。二进制表示下,取n为0的位,填上k。

#include <bits/stdc++.h>

using namespace std;

#define ll long long 

char names[111][22];

int main(){
    int t;
    cin>>t;
    while(t--){
        ll n,k;
        cin>>n>>k;
        
        ll ans = 0;
        ll tmp = 1;
        while(k){
            while(n&tmp){
                tmp<<=1;
            }
            if(k&1)ans|=tmp;
            tmp<<=1;
            k>>=1;
        }
        
        cout<<ans<<endl;
    }
    
    return 0;
}

06 01 Matrix

统计两个方向的前缀和(左,上),然后小到大推出来。

#include <bits/stdc++.h>

using namespace std;

#define ll long long 

char mat[1010][1010];
int L[1010][1010];
int U[1010][1010];
int MAX[1010][1010];
int cnt[1010];
int ans[1010];

int main(){
    int t;
    cin>>t;
    while(t--){
        memset(cnt,0,sizeof(cnt));
        memset(ans,0,sizeof(ans));
        
        int n;
        int m;
        cin>>n>>m;
        for(int i=0;i<n;i++){
            scanf("%s",mat[i]);
            for(int j=0;j<n;j++){
                mat[i][j]-='0';
            }
        }
        
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(mat[i][j]){
                    L[i][j]=1;
                    U[i][j]=1;
                    MAX[i][j]=1;
                    if(i>0){
                        U[i][j]=U[i-1][j]+1;
                    }
                    if(j>0){
                        L[i][j]=L[i][j-1]+1;
                    }
                    if(i>0&&j>0){
                        int tmp=min(L[i][j],U[i][j]);
                        MAX[i][j]=min(tmp,MAX[i-1][j-1]+1);
                    }
                }else{
                    L[i][j]=0;
                    U[i][j]=0;
                    MAX[i][j]=0;
                }
            }
        }
        
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(MAX[i][j])cnt[MAX[i][j]]++;
            }
        }
        
        for(int i=n;i>0;i--){
            cnt[i]+=cnt[i+1];
        }
        
        for(int i=1;i<=m;i++){
            int q;
            scanf("%d",&q);
            printf("%d\n",cnt[q]);
        }
    }
    return 0;
}

07 Pick Game

看完题想都没想写了个miniMax+alapha-beta pruning,结果无限T,都是PKU游戏大赛害的。其实这个题是可以用dp做的。需要把状态编码一下,也就是哪些格子被拿了哪些没有,然后就是状态的范围太大要哈希。

#include <bits/stdc++.h>

using namespace std;

#define ll long long 

const int INF = 1e9;

int v[9][9];

int n,m;
int tot;

int enCode(){
    int p=1;
    int res=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(v[i][j]){
                res|=p;
            }
            p<<=1;    
        }
    }
    return res;
}

bool canPick(int nn,int mm){
    int cnt=0;
    if(!v[nn-1][mm])cnt++;
    if(!v[nn][mm-1])cnt++;
    if(!v[nn+1][mm])cnt++;
    if(!v[nn][mm+1])cnt++;
    return cnt>=2;
}

const int mod = 1000007;

int head[mod+1];
int pre[mod*4];
int dp[mod*4];
int val[mod*4];
int cnt=0;

int find(int x){
    int xx=x%mod;
    for(int i=head[xx];~i;i=pre[i]){
        if(val[i]==x)return dp[i];
        
    }
    return -1;
}

void insert(int x,int data){
    int xx=x%mod;
    pre[cnt]=head[xx];
    head[xx]=cnt;
    val[cnt]=x;
    dp[cnt]=data;
    cnt++;
}

int ab(int dep){
    if(dep>tot)return 0;
    int code = enCode();
    if(find(code)!=-1){
        return find(code);
    }
    
    int res;
    if(dep&1){
        res=-INF;
    }else{
        res=INF;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(v[i][j] && canPick(i,j)){
                //make
                int tmp=v[i][j];
                v[i][j]=0;
                //
                if(dep&1){    //me
                    res = max(res, ab(dep+1) + tmp);
                }else{        //op
                    res = min(res, ab(dep+1) - tmp);
                }
                //unmake
                v[i][j]=tmp;
            }
            //
        }
    }
    
    insert(code,res);
    return res;
}

int main(){
    int t;
    cin>>t;
    while(t--){
        memset(v,0,sizeof(v));
        memset(dp,0,sizeof(dp));
        memset(head,-1,sizeof(head));
        cnt=0;
        
        cin>>n>>m;
        
        tot=n*m;
        int sum = 0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                cin>>v[i][j];
                sum+=v[i][j];
            }
        }
        
        int ans = ab(1);
        cout<<(sum-ans)/2+ans<<endl;
    }
    return 0;
}

08 Study Words

模拟。恰当利用STL。

#include <bits/stdc++.h>

using namespace std;

#define ll long long 

const string os="<oldwords>";
const string ot="</oldwords>";
const string as="<article>";
const string at="</article>";

map<string,int> mp;
set<string> dic;

void fun(string tmp){
    string realStr="";
    int len = tmp.size();
    for(int i=0;i<len;i++){
        if(tmp[i]>='A' && tmp[i]<='Z'){
            tmp[i]+=32;
        }
        if(tmp[i]>='a' && tmp[i]<='z'){
            realStr+=tmp[i];
        }else{
            if(realStr.size() && !dic.count(realStr)){
                mp[realStr]++;
                
            }realStr="";
        }
    }
    if(realStr.size() && !dic.count(realStr)){
        mp[realStr]++;
        realStr="";
    }
}

set<pair<int,string> > ans;

int main(){
    int t;
    cin>>t;
    while(t--){
        dic.clear();
        mp.clear();
        
        string tmp;
        while(cin>>tmp){
            if(tmp==os)continue;
            if(tmp==ot)break;
            for(int i=0;i<tmp.size();i++){
                if(tmp[i]>='A' && tmp[i]<='Z'){
                    tmp[i]+=32;
                }
            }
            dic.insert(tmp);
        }
        
        while(cin>>tmp){
            if(tmp==as)continue;
            if(tmp==at)break;
            fun(tmp);
            
        }
        
        ans.clear();
        map<string,int>::iterator it;
        for(it=mp.begin();it!=mp.end();it++){
            ans.insert(make_pair(-it->second,it->first));
        }
        
        int cnt = 10;
        set<pair<int,string> >::iterator it2;
        for(it2=ans.begin();it2!=ans.end();it2++){
            cnt--;
            cout<< (*it2).second<<endl;
            if(!cnt)break;
        }
        cout<<endl;
    }
    return 0;
}

09 The Magic Tower

模拟。


总的来说,题目都是入门级的,只有07有点难。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值