Codeforces Round #459 (Div. 2) 题目题解

A.Eleven(水题)

/**
题目翻译:给出一个N,输出一个N个字符组成的名字。
第i个字符是斐波那契数则输出'O',其他情况均输出小
'o'。
*/
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>

using namespace std;

int vis[1005];
void fun() {
    memset(vis,0,sizeof(vis));
    int num1 = 1;
    int num2 = 1;
    vis[1] = 1;
    for(int i = 3; i <= 16; i++) {
        int temp = num1+num2;
        vis[temp] = 1;
        num2 = num1;
        num1 = temp;
    }
}
int main() {
    fun();
    int N;
    while(~scanf("%d",&N)) {
        for(int i = 1; i <= N; i++) {
            if(vis[i]) {
                printf("O");
            }
            else {
                printf("o");
            }
        }
        printf("\n");
    }
    return 0;
}
B.Radio Station (水题)

/**
题目翻译:这个题目让作的工作非常像计算机网络中的DNS,
域名解析服务器的工作的逆过程(因为DNS是根据域名找IP地址,
而本题是根据IP找相应名字)。给出N个服务器的名字和IP地址,
服务器名字可能有相同的,但是IP地址是唯一的,然后给出M个
名字和IP,找IP对应的服务器的名字。
题目中N和M都高达1000,直接查找比对时间复杂度1000*1000,
不会有什么问题,如果可以借助二分查找,则会更快一些。
*/
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <math.h>
#include <algorithm>

using namespace std;

struct infor {
    char name[15];
    char ip[30];
}a[1200];
bool cmp(infor b,infor c) {
   if(strcmp(b.ip,c.ip)<0) {
        return true;
   }
   return false;
}
int binarySearch(int left,int right,char value[]) {
    int mid;
    while(left<=right) {
        mid = (left+right)/2;
        if(strcmp(value,a[mid].ip) == 0) {
            return mid;
        }
        else if(strcmp(value,a[mid].ip) > 0) {
            left = mid + 1;
        }
        else {
            right = mid - 1;
        }
    }
    return -1;
}
int main() {
    int N,M;
    while(~scanf("%d%d",&N,&M)) {
        for(int i = 0; i < N; i++) {
           scanf("%s%s",a[i].name,a[i].ip);
        }
        sort(a,a+N,cmp);
        char name[15],ip[30];
        while(M--) {
            scanf("%s%s",name,ip);
            int len = strlen(ip);
            ip[len-1] = '\0';
            int pos = binarySearch(0,N-1,ip);
            printf("%s %s; #%s\n",name,ip,a[pos].name);
        }
    }
    return 0;
}
C.The Monster(思维:区间枚举+模拟)

/**
题目翻译:给出一个字符串,只由'(' ')' '?'三种字符构成。
题目规定括号匹配的序列是合法序列,对于给定字符串中的?
它可以代表'('或')',问给出的字符串中有多少个合法的子串。

解题思路:比赛的时候,觉得每个问号两种状态,以为是个DP,
写了半天没写出来,后来看别人的题解,是一个模拟题目。思路
枚举所有区间,起初把所有遇到的?当作右括号处理。
match用来表示当前匹配状态,cnt被当作右括号的问号个数。
(1)当前字符是'(':match++
(2)当前字符是')':match--
(3)当前字符是'?':match--;cnt++
在此过程中只要出现match为0,代表当前区间匹配。
当match<0,则说明当前序列是右括号开头,则需要看之前还
有没有被当作右括号的问号,如果存在,则把其中一个变成
左括号,让序列重新以左括号开头,如果不存在,则以右括号
开头的序列永远不可能匹配,可以直接结束。
*/
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <math.h>
#include <algorithm>

using namespace std;

char str[10002];
int main() {
    while(~scanf("%s",str)) {
        int match,ans,cnt;
        ans = 0;
        int len = strlen(str);
        for(int i = 0; i < len; i++) {
            match = cnt = 0;
            for(int j = i; j < len; j++) {
                if(str[j] == '(') {
                    match++;
                }
                else if(str[j] == ')') {
                    match--;
                }
                else {  //问号先按')'处理
                    match--;
                    cnt++;
                }
                //区间合法
                if(match == 0) {
                    ans++;
                }
                //出现右括号开头的情况
                if(match < 0) {
                    if(cnt){   //还存在当作')'的问好,把它变成左括号。
                        cnt--;
                        match = 1;
                    }
                    else {
                        break;
                    }
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
D.MADMAX(难题:博弈+DP+记忆化搜索)

/**
题目翻译:给出一个N个顶点,M条边的有向无环图。每条边上
都有一个字符(小写字母)。Max和Lucas一起玩游戏,Max先手,
Lucas后手,然后他们选择各自初始顶点开始游戏,两个人轮流
沿着图中的边走,如果某条边可走当且仅当该边上的字符大于等于
上一次对手走过边的字符。最后谁先无法前进谁输。根据初始两人
所处的不同位置判断两个人的输赢情况,Max赢输出A,否则输出B。

解题思路:
DP + 记忆化搜索。
dp[x][y][z] 代表先手在x,后手在y,字符为z的时候,先手是输是赢。
如果先手赢,dp[x][y][z]=1,否则dp[x][y][z] = 0.
对于x能走的一条边,假如该边通向u,字符为ch,假如x走该边,则看
dp[y][u][ch]的值。
(1)dp[y][u][ch] = 1.则x走该边输,则不走该边继续考虑走别的边。
(2)dp[y][u][ch] = 0.则x走该边赢,则dp[x][y][z] = 1.
只有x所有的出边走了后都会输,则x必输。由于两人游戏均选择最优策略。
则只要x有一条出边使它赢,则x必赢。
*/
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <math.h>
#include <queue>

using namespace std;

const int maxn = 102;
int Map[maxn][maxn]; //存放地图
int N,M;
int dp[maxn][maxn][26];
void init() {
    for(int i = 1; i <= N;i++) {
        for(int j = 1; j <= N; j++) {
            Map[i][j] = -1;
        }
    }
    memset(dp,-1,sizeof(dp));
}
int dfs(int x,int y,int z) {
    if(dp[x][y][z] != -1)
        return dp[x][y][z];
    dp[x][y][z] = 0;
    for(int i = 1; i <= N; i++) {
        if(Map[x][i] >= z) {
            if(dfs(y,i,Map[x][i])==0){
                dp[x][y][z] = 1;
                break;
            }
        }
    }
    return dp[x][y][z];
}
int main() {
    while(~scanf("%d%d",&N,&M)) {
        init();  //初始化地图。
        int u,v;
        char ch;
        for(int i = 0; i < M; i++) {
            scanf("%d%d %c",&u,&v,&ch);
            Map[u][v] = ch-'a';
        }
        for(int i = 1; i <= N; i++) {
            for(int j = 1; j <= N; j++) {
                if(dfs(i,j,0)) {
                    printf("A");
                }
                else {
                    printf("B");
                }
            }
            printf("\n");
        }
    }
    return 0;
}






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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值