喵哈哈村的魔法考试 Round #9 (Div.2) 题解

A题 喵哈哈村的数据筛选游戏

题解:这道题签到题,拿个数组记录一下这个数是否出现过即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int vis[maxn];
int n;
int a[maxn];
int main(){
    while(cin>>n){
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;i++){
            cin>>a[i];
        }
        int flag = 0;
        for(int i=0;i<n;i++){
            if(vis[a[i]]==0){
                vis[a[i]]=1;
                if(flag==0){
                    cout<<a[i],flag=1;

                }
                else cout<<" "<<a[i];
            }
        }
        cout<<endl;
    }
}

B题:喵哈哈村的扔硬币游戏

题解:直接暴力更新应该也能过,这里我提倡一种前缀和的做法,每次操作的时候只要看这个点被更新了奇数次还是偶数次就好了。

前缀和的具体方式看代码:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5+7;

int a[maxn];

int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int A,B;
        scanf("%d%d",&A,&B);
        a[A]++;
        a[B+1]--;
    }
    int sum = 0;
    for(int i=1;i<=n;i++){
        sum+=a[i];
        if(sum%2==0)printf("0");
        else printf("1");
    }
    printf("\n");
}

C题:喵哈哈村的三角形游戏

三角插值实际上就是假设三个顶点为p1,p2,p3,那么所有三角形内的点都满足

p.x = ap1.x+bp2.x+cp3.x;
p.y = a
p1.y+bp2.y+cp3.y;
a+b+c = 1

解这个方程得到a,b,c

然后再算p.w = ap1.w+bp2.w+c*p3.w即可。

判断是否在三角形内部,用计算几何的叉积或者面积法都可以。

#include<bits/stdc++.h>
using namespace std;
const double eps = 1e-6;
double x1,yy1,z1,x2,y2,z2,x3,y3,z3;
double x,y;
struct node{
    double x,y;
    double w;
}p[5];
double dis(node A,node B){
    return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

double area(node A,node B,node C){
    double len1 = dis(A,B),len2 = dis(B,C),len3 = dis(A,C);
    double p = (len1+len2+len3)/2;
    return sqrt(p*(p-len1)*(p-len2)*(p-len3));
}
bool equ(double A,double B){
    if(fabs(A-B)<eps)return true;
    return false;
}
int main(){
    while(cin>>p[0].x>>p[0].y>>p[0].w){
        for(int i=1;i<3;i++)
            cin>>p[i].x>>p[i].y>>p[i].w;
        cin>>p[3].x>>p[3].y;
        for(int i=3;i>=0;i--){
            p[i].x-=p[0].x;
            p[i].y-=p[0].y;
        }
        if(equ(area(p[0],p[1],p[2]),area(p[0],p[1],p[3])+area(p[0],p[2],p[3])+area(p[1],p[2],p[3]))==false){
            cout<<"-1"<<endl;
            continue;
        }
        double B = (p[1].x*p[3].y-p[3].x*p[1].y)/(p[1].x*p[2].y-p[2].x*p[1].y);
        double A;
        if(equ(p[1].x,0)==false)A = (p[3].x-B*p[2].x)/p[1].x;
        else A = (p[3].y-B*p[2].y)/p[1].y;
        printf("%.2f\n",A*p[1].w+B*p[2].w+(1.0-A-B)*p[0].w);
    }
}

D:喵哈哈村的修路游戏

答案显然为连通块的数量-1,随便拿个东西算连通块的数量就好了。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e3+7;
vector<int> E[maxn];
int n,m;
int vis[maxn],cnt=0;
void dfs(int x){
    vis[x]=1;
    for(int i=0;i<E[x].size();i++){
        if(!vis[E[x][i]])
            dfs(E[x][i]);
    }
}
int main(){
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        E[a].push_back(b);
        E[b].push_back(a);
    }
    for(int i=1;i<=n;i++){
        if(!vis[i]){
            cnt++;
            dfs(i);
        }
    }
    cout<<cnt-1<<endl;
}

E:喵哈哈村的打印机游戏

区间DP,dp[l][r][d]表示区间[l,r],当前底色为d的最小花费。

然后枚举中间的节点进行转移就好了,具体看代码,是一道中规中矩的区间DP题目。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 106;
int dp[maxn][maxn][maxn];
const int inf = 1e8;
string s;
int solve(int l,int r,int d){
    if(l>r)return 0;
    if(s[l]-'A'==d&&l==r)return dp[l][r][d]=0;
    if(l==r)return dp[l][r][d]=1;
    if(dp[l][r][d]!=-1)return dp[l][r][d];
    dp[l][r][d]=inf;
    for(int i=0;i<26;i++){
        dp[l][r][d]=min(dp[l][r][d],solve(l,r,i)+1);
    }
    if(s[l]-'A'==d)dp[l][r][d]=min(dp[l][r][d],solve(l+1,r,d));
    if(s[r]-'A'==d)dp[l][r][d]=min(dp[l][r][d],solve(l,r-1,d));
    for(int i=l+1;i<r;i++){
        if(s[i]-'A'==d){
            dp[l][r][d]=min(dp[l][r][d],solve(l,i-1,d)+solve(i+1,r,d));
        }
    }
    return dp[l][r][d];
}
int main(){
    while(cin>>s){
        memset(dp,-1,sizeof(dp));
        cout<<solve(0,s.size()-1,27)<<endl;
    }
}
posted @ 2017-03-20 20:48  qscqesze  阅读(289)  评论(0编辑  收藏  举报