程序设计思维与实践 CSP-M4 (3/4/数据班)

A-TT数鸭子

题意:
这一天,TT因为疫情在家憋得难受,在云吸猫一小时后,TT决定去附近自家的山头游玩。

TT来到一个小湖边,看到了许多在湖边嬉戏的鸭子,TT顿生羡慕。此时他发现每一只鸭子都不一样,或羽毛不同,或性格不同。TT在脑子里开了一个map<鸭子,整数> tong,把鸭子变成了一些数字。现在他好奇,有多少只鸭子映射成的数的数位中不同的数字个数小于k。
思路:
这道题的数据范围就是一个坑!!!其实k最大也就是10。我郁闷了半天,最后也没提交代码,唉!
通过mod 10的方法取得每一位,最后统计出现过的数字个数就可以了。
代码:

#include 
using namespace std;
const int maxn = 11;
int n, k, a[maxn], ans;
int main()
{
    scanf("%d %d", &n, &k);
    for (int i = 1; i <= n; i++)
    {
        long long x = 0;
        scanf("%lld", &x);
        while (x)
        {
            a[x % 10]++;
            x /= 10;
        }
        int temp = 0;
        for (int j = 0; j < 10; j++)
        {
            if (a[j])
            {
                temp++;
                a[j] = 0;
            }
        }
        if (temp < k)
            ans++;
    }
    printf("%d\n", ans);
    //system("pause");
}

B-ZJM要抵御宇宙射线

题意:
据传,2020年是宇宙射线集中爆发的一年,这和神秘的宇宙狗脱不了干系!但是瑞神和东东忙于正面对决宇宙狗,宇宙射线的抵御工作就落到了ZJM的身上。假设宇宙射线的发射点位于一个平面,ZJM已经通过特殊手段获取了所有宇宙射线的发射点,他们的坐标都是整数。而ZJM要构造一个保护罩,这个保护罩是一个圆形,中心位于一个宇宙射线的发射点上。同时,因为大部分经费都拨给了瑞神,所以ZJM要节省经费,做一个最小面积的保护罩。当ZJM决定好之后,东东来找ZJM一起对抗宇宙狗去了,所以ZJM把问题扔给了你~
思路:
就是求解最小最大值问题,枚举每个点到其他点的距离,然后取最大值,再对于所有的最大值取最小值。O(n^2)解决问题。
值得注意的是,题目是要距离的平方,好坑。
代码:

#include 
#include 
#include 
using namespace std;
const int maxn = 1000 + 10;
int n;
struct Node
{
    int x, y;
} node[maxn];
double distance(Node a, Node b)
{
    return pow(a.x - b.x, 2) + pow(a.y - b.y, 2);
}
int main()
{
    cin >> n;
    for (int i = 0; i < n; i++)
        cin >> node[i].x >> node[i].y;
    double ans = 0;
    double tnt = 0;
    int m = 0;
    for (int i = 1; i < n; i++)
        ans = max(ans, distance(node[0], node[i]));
    for (int i = 1; i < n; i++)
    {
        tnt = 0;
        for (int j = 0; j < n; j++)
        {
            if (i == j)
                continue;
            tnt = max(tnt, distance(node[i], node[j]));
        }
        if (ans > tnt)
            ans = tnt, m = i;
        else if (ans == tnt && (node[i].x < node[m].x || (node[i].x == node[m].x && node[i].y < node[m].x)))
            m = i;
    }
    cout << setiosflags(ios::fixed) << setprecision(2);
    cout << node[m].x << ".00"
         << " " << node[m].y << ".00" << endl;
    cout << ans;
    //system("pause");
}

C-宇宙狗的危机

题意:
在瑞神大战宇宙射线中我们了解到了宇宙狗的厉害之处,虽然宇宙狗凶神恶煞,但是宇宙狗有一个很可爱的女朋友。

最近,他的女朋友得到了一些数,同时,她还很喜欢树,所以她打算把得到的数拼成一颗树。

这一天,她快拼完了,同时她和好友相约假期出去玩。贪吃的宇宙狗不小心把树的树枝都吃掉了。所以恐惧包围了宇宙狗,他现在要恢复整棵树,但是它只知道这棵树是一颗二叉搜索树,同时任意树边相连的两个节点的gcd(greatest common divisor)都超过1。

但是宇宙狗只会发射宇宙射线,他来请求你的帮助,问你能否帮他解决这个问题。
思路:
这题自己一开始是没有思路的,后来想了想,可以用区间dp的方法去做。
我们定义两个数组:l[i][j],r[i][j]分别表示以i为根,向左到j可以作为i的左子树,向右到j可以作为i的右子树。这是表示的树结构,所以非常重要。

然后用dp[i][j]表示i∼j能构成一棵树。函数最后返回dp[1][n]]。
当l[k][i]==r[k][j]==true时,dp[i][j]=true,此时i∼j是以k为根的二叉搜索树。
状态转移方程如下:

  • l[j+1][i]∣=gcd(a[j+1],a[k]),(i≤k≤j)
  • r[i−1][j]∣=gcd(a[i−1],a[k]),(i≤k≤j)
    就是说,j+1可以作为k的父亲,k是其左儿子,这样由下而上的构建出二叉搜索树。
    代码:
#include 
#include 
#include 
#include 
using namespace std;
const int maxn = 700 + 100;
int t, n, a[maxn];
bool dp[maxn][maxn], g[maxn][maxn], l[maxn][maxn], r[maxn][maxn];
int gcd(int _a, int _b) { return _b == 0 ? _a : gcd(_b, _a % _b); }
bool IsBinarySearchTree()
{
    for (int len = 1; len <= n; len++)
    {
        for (int i = 1; i <= n - len + 1; i++)
        {
            int j = i + len - 1;
            for (int k = i; k <= j; k++)
            {
                if (l[k][i] && r[k][j])
                {
                    dp[i][j] = true;
                    l[j + 1][i] |= g[j + 1][k];
                    r[i - 1][j] |= g[i - 1][k];
                }
            }
        }
    }
    return dp[1][n];
}
int main()
{
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        memset(l, false, sizeof(l));
        memset(r, false, sizeof(r));
        memset(dp, false, sizeof(dp));
        for (int i = 1; i <= n; i++)
        {
            l[i][i] = r[i][i] = dp[i][i] = true;
            for (int j = 1; j <= n; j++)
                g[i][j] = gcd(a[i], a[j]) > 1;
        }
        if (IsBinarySearchTree())
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}

你可能感兴趣的:(实验报告)