【新疆大学ACM-ICPC程序设计竞赛五月月赛(同步赛) 】 A B C D F J

A Red Rover

链接:https://www.nowcoder.com/acm/contest/116/A
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
这里写图片描述
输入描述:
Input consists of a single line containing a string made up of the letters N, S, E, and W representing the route to transmit to the rover. The maximum length of the string is 100.
输出描述:
Display the minimum number of characters needed to encode the route.
示例1
输入
WNEENWEENEENE
输出
10
分析: n, 这么小,暴力就行
代码

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

typedef long long ll;
typedef unsigned long long ull;

const int N = (int) 500 + 11;
const int M = (int) 1e6 + 11;
const int inf = 0x3f3f3f3f;


int solve(string s, string t){
    int cnt = 0; int len =s.size();
    int pos;
    while((pos = s.find(t)) < s.size()){
        cnt ++;
        s = s.substr(pos + t.size(), s.size());
    }
    if(cnt <= 1) return len;  // 注意这里 必须要重复  即 至少出现两次
    else return  len - t.size() * cnt +  t.size() + cnt;
}

int main(){
    string s, t;
    while(cin >> s){
        int len = s.size();
        int mx = inf;
        for(int i = 0; s[i]; i++){
            t = "";
            for(int j = i; s[j]; j++){
                t += s[j];
                mx  = min(mx, solve(s, t));
            }
        }

        printf("%d\n", mx);
    }
    return 0;
}

B 杨老师的游戏

链接:https://www.nowcoder.com/acm/contest/116/B
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
杨老师给同学们玩个游戏,要求使用乘法和减法来表示一个数,他给大家9张卡片,然后报出一个数字,要求大家用表达式的形式来表示出这个数
100 可以表示为这样的形式:100 = 129*67-8543 , 还可以表示为:100 = 13*489-6257
注意特征:表达式中,数字1~9分别出现且只出现一次(不包含0)。
类似这样的表达式,100 有 20 种表示法。
题目要求:
从标准输入读入一个正整数N(N<1000 * 1000)
程序输出该数字用数码1~9不重复不遗漏地组成的全部种数。
注意:不要求输出每个表示,只统计有多少表示法!
输入描述:
一个正整数N
输出描述:
输出有多少种表示法
示例1
输入
100
输出
20
备注:
注意只有一个乘法和一个减法,*号保证在-的前面

分析: 暴力枚举就行了。
代码

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

typedef long long ll;
typedef unsigned long long ull;

string s = "123456789";
int Judge(int a, int b, int n){
    ll x = 0; ll y = 0; ll z = 0;
    for(int i = 0; i < a; i++) x = x * 10 + s[i] - '0';
    for(int i = a; i < b; i++) y = y * 10 + s[i] - '0';
    for(int i = b; i < 9; i++) z = z * 10 + s[i] -'0';
    return (x * y - z)  == n ;
}

int main(){
    int n; scanf("%d", &n);
    int cnt = 0;
    do{
        for(int i = 1; i < 8; i++){
            for(int j = i + 1; j < 9; j++) {
                cnt += Judge(i, j, n);
            }
        }
    }
    while(next_permutation(s.begin(), s.end())) ;
    printf("%d\n", cnt);
return 0;
}

C 勤奋的杨老师

链接:https://www.nowcoder.com/acm/contest/116/C
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
杨老师认为他的学习能力曲线是一个拱形。勤奋的他根据时间的先后顺序罗列了一个学习清单,共有n个知识点。但是清单中的知识并不是一定要学习的,可以在不改变先后顺序的情况下有选择的进行学习,而每一个知识点都对应一个难度值。杨老师希望,后学习的知识点的难度一定不低于前一个知识点的难度(i < j 时ai<=aj),而可能存在一个临界点,在临界点以后,他希望后学习的知识点的难度一定不高于前一个知识点的难度( i < j时ai>=aj)。杨老师想尽可能多的学习知识。请问:杨老师最多可以学习多少知识?
输入描述:
第一行:一个整数n(0 < n < 500000)接下来一行:n个整数,第i个整数ai(0<=ai<500000)表示第i道题目的难度。
输出描述:
一行一个整数,表示杨老师最多可以学习多少个知识。
示例1
输入
5
1 4 2 5 1
输出
4
分析: 两遍 LIS 就行了 ,然后枚举 间断的那个位置 ,取最多就行。
代码

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

typedef long long ll;
typedef unsigned long long ull;

const int N = (int) 500000 + 11;
const int M = (int) 1e6 + 11;

int a[N + 1];
int dp[N + 1];
int dp1[N + 1], dp2[N + 1];

int main(){
    int n; scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%d", &a[i]);

    int len = 1; dp[len] = a[1];
    dp1[1] = 1;
    for(int i = 2; i <= n; i++) {
        if(a[i] >= dp[len]) dp[++len] = a[i];
        else
            dp[upper_bound(dp, dp+ len , a[i]) - dp] = a[i];

        dp1[i] = len;
    }
    reverse(a + 1, a + 1 + n);
    //for(int i = 1; i <= n; i++) printf("%d ", dp1[i]); puts("");

    len = 1; dp[len] = a[1];
    dp2[1] = 1;
    for(int i = 2; i <= n; i++) {
        if(a[i] >= dp[len]) dp[++len] = a[i];
        else
            dp[upper_bound(dp, dp + len, a[i]) - dp] = a[i];

        dp2[i] = len;
    }
    //for(int i = 1; i <= n; i++) printf("%d ", dp2[i]);

    int ans  = 0;
    for(int i = 1; i <= n; i++){
        ans = max(ans, dp1[i] + dp2[n - i]);
    }
    printf("%d\n", ans);
return 0;
}

D 勤奋的杨老师(二)
链接:https://www.nowcoder.com/acm/contest/116/D
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
众所周知,杨老师是一位十分勤奋的老师,他非常的热爱学习。

勤奋的他为自己罗列了一个学习清单,共有n个知识点,他可以有选择的进行学习。

每个知识点都会对应0个或1个或多个先修知识点(只有学会了先修知识点才能学习该知识点),同时每个知识点都有一个智慧值和一个智力消耗值。

扫描二维码关注公众号,回复: 2563057 查看本文章

杨老师希望在进行过激烈的学习之后,他的收获可以·量化为所有学过的题的智慧值的和与智力消耗值的和的差值。请问,这个值最大是多少?

输入描述:
第一行:一个整数n(n<=500)接下来n行,每行两个整数,代表第i个知识点的智慧值和智力消耗值接下来若干行,每行2个整数u, v,代表u是v的先修知识点。
输出描述:
一行,表示杨老师的收获的最大值
示例1
输入
4
5 1
2 1
1 2
1 2
3 1
2 4
2 1
输出
4
分析: 最大权闭合图的裸题

代码

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

typedef long long ll;
typedef unsigned long long ull;

const int N = (int) 500 + 11;
const int M = (int) 1e6 + 11;
const ll inf = 0x3f3f3f3f3f3f3f3f;

struct Edge {
    int form,to; ll cap,flow; int nexts;
    Edge() {}
    Edge(int _form, int _to, ll _cap, ll _flow, int _nexts){
        form = _form; to = _to; cap = _cap; flow = _flow; nexts = _nexts;
    }
}edge[M];
int head[N],top;
void init(){
    memset(head,-1,sizeof(head));
    top=0;
}
void addedge(int a,int b,ll c){
    edge[top]=Edge(a, b, c, 0, head[a]);
    head[a] = top++;
    edge[top]=Edge(b, a, 0, 0, head[b]);
    head[b]=top++;
 }
int vis[N],dis[N];
int cur[N];
bool bfs(int st,int ed){
    queue<int>Q;
    memset(vis,0,sizeof(vis));
    memset(dis,-1,sizeof(dis));
    Q.push(st);vis[st]=1;dis[st]=1;
    while(!Q.empty()){
        int now=Q.front();Q.pop();
        for(int i=head[now];i!=-1;i=edge[i].nexts){
            Edge e=edge[i];
            if(!vis[e.to]&&e.cap-e.flow>0){
                vis[e.to]=1;
                dis[e.to]=dis[now]+1;
                if(e.to==ed) return 1;
                Q.push(e.to);
            }
        }
    }
    return 0;
}
ll dfs(int now,ll a,int ed){
    if(a==0||now==ed) return a;
    ll flow=0,f;
    for(int &i=cur[now];i!=-1;i=edge[i].nexts){
        Edge &e=edge[i];
        if(dis[e.to]==dis[now]+1&&(f=dfs(e.to,min(e.cap-e.flow,a),ed))>0){
            e.flow+=f;
            flow+=f;
            edge[i^1].flow-=f;
            a-=f;
            if(a==0) break;
        }
    }
    return flow;
}
ll max_flow(int st ,int ed){
    ll flow=0;
    while(bfs(st,ed)){
        memcpy(cur,head,sizeof(head));
        flow+=dfs(st,inf,ed);
    }
    return flow;
}
int main(){
    init();
    int n; scanf("%d", &n);
    int S = 0, T = n + 1;
    ll ans = 0; ll a, b;
    for(int i = 1; i <= n; i++){
        scanf("%lld%lld", &a, &b);
        if(a >= b) {
            ans += a - b;
            addedge(S, i, a - b);
        }else {
            addedge(i, T, b - a);
        }
    }

    while(scanf("%d%d", &a, &b) != EOF) addedge(b, a, inf);

    printf("%lld\n", ans - max_flow(S, T));
return 0;
}

F 猴子排序的期望

链接:https://www.nowcoder.com/acm/contest/116/F
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
我们知道有一种神奇的排序方法叫做猴子排序,就是把待排序的数字写在卡片上,然后让猴子把卡片扔在空中,等落下的时候观察这些卡片是否从左到右已经排序完成(我们认为不会发生卡片落地后叠在一起的情况)如果有序则排序完成,否则让猴子再扔一遍,直到卡片有序,那么问题来了,给你N个卡片,每个卡片上写着一个大写字母,请问猴子第一次扔这些卡片就按字典序排序完成的概率有多大?

输入描述:
第一行是一个整数N(1 < N < 100)表示给猴子N张卡片,接下来是一个长度为N的字符串,代表这些卡片上所写的字母。
输出描述:
输出一行,表示猴子排序第一次就成功的概率(用分子为1的分数表示)。
示例1
输入
7
SCIENCE
输出
1/1260
分析: 我们只要求出 用所给字符随意排列可以构成多少种不同的排列不就行了
高中学过。
代码

import java.io.*;
import java.util.*;
import java.math.*;

public class Main  {
    public static final int N = 100 + 11;
    public static BigInteger[] fac = new BigInteger[N + 1];
    public static int[] cnt = new int[N];
    public static void init(){
        fac[0] = new BigInteger("1"); int j  = 1;
        for(BigInteger i = new BigInteger("1"); j < N; i = i.add(new BigInteger("1") ), j++) {
            fac[j] = fac[j - 1].multiply(i);  
        }
    }

    public static void main (String[] args) {
        init();
        Scanner cin = new Scanner (System.in);
        int n  = cin.nextInt();
        String str  = cin.next();
        for(int i = 0; i < str.length(); i++) {
           // System.out.println(str.charAt(i));
            cnt [(str.charAt(i) - 'A')] ++;
        }
        BigInteger ans = fac[n];
        //System.out.println(ans);
        for(int i = 0; i < 26; i++){
            ans = ans.divide(fac[cnt[i]]);
        }
        System.out.println("1/"+ans);
    }
}

J Most Powerful

链接:https://www.nowcoder.com/acm/contest/116/J
来源:牛客网

时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
Recently, researchers on Mars have discovered N powerful atoms. All of them are different. These atoms have some properties. When two of these atoms collide, one of them disappears and a lot of power is produced. Researchers know the way every two atoms perform when collided and the power every two atoms can produce.

You are to write a program to make it most powerful, which means that the sum of power produced during all the collides is maximal.
输入描述:
There are multiplecases. The first line of each case has an integer N (2 <= N <= 10), whichmeans there are N atoms: A1, A2, … , AN.Then N lines follow. There are N integers in each line. The j-th integer on thei-th line is the power produced when Ai and Aj collidewith Aj gone. All integers are positive and not larger than 10000.

The last case isfollowed by a 0 in one line.

There will be no morethan 500 cases including no more than 50 large cases that N is 10.

输出描述:
Output the maximalpower these N atoms can produce in a line for each case.
示例1
输入
2
0 4
1 0
3
0 20 1
12 0 1
1 10 0
0
输出
4
22

分析: 从结果上看,最后一定是有一个消失的顺序 使其最后的值最大。我们可以暴力枚举这个顺序,然后 再求出当前顺序下可以得到的最大权值,最后再取最大。那么给定固定的顺序,怎么求最大权值呢,只要提前预处理好 第i个点在所有状态下的最大值就好,详细的看代码吧。
代码

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

typedef long long ll;
typedef unsigned long long ull;

const int N = (int) 500 + 11;
const int M = (int) 1e6 + 11;
const ll inf = 0x3f3f3f3f3f3f3f3f;

int n;
int mp[11][11]; int a[11];
int dp[11][1 << 11];  // dp[i][j]表示 第i个原子在j状态下爆破i的最大值
void init(){  // 预处理 dp 
    for(int i = 0; i < n; i++){
        for(int j = 0; j < (1 << n) - 1; j++){
            int mx = 0;
            for(int k = 0; k < n; k++){
                if(((j >> k) & 1) && k != i)
                    mx = max(mx, mp[k][i]);
            }
            dp[i][j] = mx;
        }
    }
}

int solve(){
    int ans = 0; int state = (1 << n) - 1;
    for(int i = 0; i < n - 1; i++){
        state ^= (1 << a[i]);
        ans += dp[a[i]][state];
    }
    return ans;
}

int main(){
    while(scanf("%d", &n) && n ){
        for(int i = 0; i < n; i++){
            for(int j = 0; j < n; j++){
                scanf("%d", &mp[i][j]);
            }
        }

        init();
        for(int i = 0; i < 11; i++) a[i] =  i;
        int ans = 0;
        do{
            ans = max(ans, solve());
        }while(next_permutation(a, a + n)) ;
        printf("%d\n", ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37383726/article/details/80260835
今日推荐