码迷,mamicode.com
首页 > 其他好文 > 详细

2014 多校赛 第一场

时间:2015-07-13 12:26:15      阅读:172      评论:0      收藏:0      [点我收藏+]

标签:

题目链接

A - Couple doubi

题意:桌上共有 k 个球,第i个球的值为 (1^i+2^i+...+(p-1)^i )mod p
DouBiXp 和 他的女朋友 DouBiNan 轮流拿球,DouBiNan先拿,
所有的球都拿完后,谁手上球的值总和更大谁就赢,
已知 k,p,且p为素数,
若DouBiNan赢输出"YES",否则输出"NO"

分析:DouBiNan先拿,为了赢肯定先拿没有被拿的球中值最大的,
找规律得 每个球的值要么为 0,要么为某个的正数x,且每p-1个球有一个的值为x
那么如果值为x的球个数如果为奇数,则DouBiNan赢,否则赢不了

#include<stdio.h>
int main()
{
    int p,n;
    while(scanf("%d%d",&n,&p)!=EOF){
        if((n/(p-1))%2)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}


D - Task
题意:有n台机器和m个任务,第i个任务需要xi时间去完成,且它的难度等级为yi
若第i个任务被完成,可获得收益 500*xi+2*yi
每台机器有一个最大工作时间和能完成的最大难度等级,
若某台机器要完成某任务,则机器的工作时间要不低于任务需要的时间,
机器的难度等级不低于任务的难度等级,
一台机器一天只能完成一次任务,且一个任务只能由一台机器完成

已知每台机器和每个任务的完成时间和难度等级,
求一天能完成的最多的任务数,在此前提下的最大收益

分析:贪心求解
收益只有完成的任务的x,y有关,且x,y越大,获得的收益越大
所以要优先完成x更大的任务,若x相等,要优先完成y大的任务
即任务要按x从大到小排序,若x相等则按y从大到小排序
任务的x按从大到小排序,再给任务匹配机器
当有多台机器符合x条件,那么要选择y满足条件的最小的y,
这样没被用的更大的y的机器,更可能符合完成其他任务

#include<stdio.h>
#include<algorithm>
#define N 100000
using namespace std;
struct stu{
    int time,level;
}task[N+10],machine[N+10];
int cmp(stu a,stu b){
    if(a.time==b.time)
        return a.level>b.level;
    return a.time>b.time;
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF){
        for(int i=1;i<=n;i++)
            scanf("%d%d",&machine[i].time,&machine[i].level);
        for(int i=1;i<=m;i++)
            scanf("%d%d",&task[i].time,&task[i].level);
        sort(machine+1,machine+1+n,cmp);
        sort(task+1,task+1+m,cmp);
        int j=1,cnt[105]={0},maxm=0;
        long long ans=0;
        for(int i=1;i<=m;i++){
            while(j<=n&&task[i].time<=machine[j].time){
                cnt[machine[j].level]++;
                j++;
            }
            for(int k=task[i].level;k<=100;k++){
                if(cnt[k]){
                    maxm++;
                    ans+=task[i].time*500+task[i].level*2;
                    cnt[k]--;
                    break;
                }
            }
        }
        printf("%d %I64d\n",maxm,ans);
    }
    return 0;
}


E - Peter‘s Hobby

题意:已知昨天天气与今天天气状况的概率关系(wePro),和今天天气状态和叶子湿度的概率关系(lePro)
第一天为sunny 概率为 0.63,cloudy 概率 0.17,rainny 概率 0.2.
给定n天的叶子湿度状态,求这n天最可能的天气情况

分析:概率dp
设 dp[i][j] 表示第i天天气为j的最大概率,
pre[i][j]表示第i天天气最可能为j的前一天天气,
dp[i][j]=max(dp[i-1][k]+log(wePro[k][j])+log(lePro[j][lePos[i]])) (k=0,1,2 表示昨天的天气)

注:由于概率越乘越小,考虑精度原因,用log取对数
log(a*b*c) = log a + log b +log c

#include<stdio.h>
#include<string.h>
#include<math.h>
char Con[5][10]={"Dry","Dryish","Damp","Soggy"};
char We[5][10]={"Sunny","Cloudy","Rainy"};
double lePro[3][4]={0.6,0.2,0.15,0.05,
                  0.25,0.3,0.2,0.25,
                  0.05,0.10,0.35,0.50};  //叶子
double wePro[3][3]={0.5,0.375,0.125,
                    0.25,0.125,0.625,
                    0.25,0.375,0.375};   //天气
double init[3]={0.63,0.17,0.2};
double dp[55][3],pre[55][3];
int n,lePos[55];
void solve()
{
    for(int i=0;i<3;i++)
        dp[1][i]=log(init[i])+log(lePro[i][lePos[1]]);
    for(int i=2;i<=n;i++){
        for(int j=0;j<3;j++){  //今天天气
            double maxp=-1e8;
            int pos=0;
            for(int k=0;k<3;k++){  //昨天天气
                double temp=dp[i-1][k]+log(wePro[k][j])+log(lePro[j][lePos[i]]);
                if(temp>maxp){
                    maxp=temp;
                    pos=k;
                }
            }
            dp[i][j]=maxp;
            pre[i][j]=pos;
        }
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    for(int k=1;k<=T;k++){
        printf("Case #%d:\n",k);
        scanf("%d",&n);
        char con[10];
        for(int i=1;i<=n;i++){
            scanf("%s",con);
            for(int j=0;j<4;j++)
                if(strcmp(con,Con[j])==0){
                    lePos[i]=j;
                    break;
                }
        }
        solve();
        double maxp=-1e8;
        int ans[55];
        for(int i=0;i<3;i++)
        if(dp[n][i]>maxp){
            maxp=dp[n][i];
            ans[n]=i;
        }
        for(int i=n-1;i>=1;i--)
            ans[i]=pre[i+1][ans[i+1]];
        for(int i=1;i<=n;i++)
            printf("%s\n",We[ans[i]]);
    }
    return 0;
}

资料扩展:详情点此
本题属于 隐马尔可夫模型
马尔可夫模型:统计模型,每个状态只依赖于之前的状态

马尔可夫模型可用马尔可夫过程描述
我们就为上面的一阶马尔科夫过程定义了以下三个部分:
  状态:晴天、阴天和下雨
  初始向量:定义系统在时间为0的时候的状态的概率
  状态转移矩阵:每种天气转换的概率
  所有的能被这样描述的系统都是一个马尔科夫过程。

隐马尔可夫模型 (Hidden Markov Model) 是一种统计模型,用来描述一个含有隐含未知参数的马尔可夫过程。
包含隐藏状态 (如:天气状态)和 可观状态(如:叶子的湿度)
可以观察到的状态序列和隐藏的状态序列是概率相关的

版权声明:本文为博主原创文章,未经博主允许不得转载。

2014 多校赛 第一场

标签:

原文地址:http://blog.csdn.net/acm_code/article/details/46858779

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!