zoukankan      html  css  js  c++  java
  • 10.27 校内模拟赛题解报告

    T1

    题意:
    现在有连续 (n) 天,老板娘需要分配她的工作时间。
    在第 (i) 天工作每小时需要消耗 (a_i) 的精力,老板娘希望合理分配自己的工
    作时间使自己消耗尽量少的精力。
    但老板又不希望老板娘摸鱼,所以他要求老板娘对于任意的连续7天她工作的总时间都不能少于7小时。
    因为工作的特殊性,老板娘只能在每天分配整数小时的工作时间(当然能为0)。
    题解:
    DP 题。
    (f_i) 表示在第 (i) 天上班则前 (i) 天要花费的最少精力。
    先假设只需要工作一个小时,
    (f_i = min(f_i, f_j + a[i]))
    而题目中要求要工作 7 个小时,就是将工作一个小时得到的最优解乘以7。
    (f_i = min(f_i, f_j + a[i] imes 7))
    关于最后的答案。
    因为连续七天,工作 7 小时,所以只需要取最后7天中答案的最小值。

    /*
    Date:
    Source:
    Knowledge: 
    */
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define orz cout << "AK IOI" << "
    "
    #define int long long 
    
    using namespace std;
    const int maxn = 10010;
    
    int read()
    {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch <= '9' && ch >= '0') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    void print(int X)
    {
    	if(X < 0) X = ~(X - 1), putchar('-');
    	if(X > 9) print(X / 10);
    	putchar(X % 10 ^ '0');
    }
    int Max(int a, int b){
    	return a > b ? a : b;
    }
    int Min(int a, int b){
    	return a < b ? a : b;
    }
    int T, n, a[maxn], f[maxn];
    signed main()
    {
    	//freopen("job.in", "r", stdin);
    	//freopen("job.out", "w", stdout);
    	T = read();
    	while(T--)
    	{
    		n = read();
    		for(int i = 1; i <= n; i++) a[i] = read();
    		for(int i = 1; i <= n; i++) f[i] = 1e18;
    		int ans = 1e18;
    		for(int i = 1; i <= n; i++)
    		{	
    			for(int j = Max(0, i - 7); j < i; j++)
    				f[i] = Min(f[i], f[j] + a[i] * 7);
    		}
    		for(int i = Max(1, n - 6); i <= n; i++) ans = Min(ans, f[i]);
    		printf("%lld
    ", ans);
    	}
    	//fclose(stdin);
    	//fclose(stdout);
    	return 0;
    }
    /*
    2
    10
    1 6 3 2 4 5 2 1 2 7
    10
    1 1 1 1 1 1 1 1 1 1
    */
    

    我还是感觉这个 DP 好假啊!!

    T2

    题意:
    你有 (n) 个不同的球和 (m) 个不同的盒子。每个球都被分配了两个盒子,应该放在其中一个盒子里。每个盒子只能装一个球。问题是把所有的球都放到盒子里有多少种解。
    题解:
    对问题进行一个建模。
    将每个篮子看做一个点,将球看做边,那么就将问题转换成了一个这样的问题:
    有一张图,将边分配给它相邻的一个节点,且每个节点只能分配一条边,问有多少种分配方案?
    对于由这种方法建出来的图,每一个联通分量之间是互不影响的,我们只需要算出每一个联通分量中的答案利用乘法原理,进行求解。

    考虑一个联通分量。以为它是一个联通分量,所以只会有以下几种情况。

    1. 当 E > V 时,显然是无解的。
    2. 当 E = v 时,这种情况下,联通分量的形态是基环树,每个边都只会拥有一个点,只是边的方向的问题。所以当环不是自环的时候,答案为 2,否则为 1。
    3. 当V = E - 1时,这种情况下联通分量是一棵树。每一个点都可能会没有边。所以这种情况下的方案数为 V。
    /*
    Date:
    Source:
    Knowledge:
    */
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #define orz cout << "AK IOI" << "
    "
    #define int long long 
    
    using namespace std;
    const int mod = 998244353; 
    const int maxn = 3e5 + 10;
    
    int read()
    {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch <= '9' && ch >= '0') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    void print(int X)
    {
    	if(X < 0) X = ~(X - 1), putchar('-');
    	if(X > 9) print(X / 10);
    	putchar(X % 10 ^ '0');
    }
    int Max(int a, int b){
    	return a > b ? a : b;
    }
    int Min(int a, int b){
    	return a < b ? a : b;
    }
    int T, n, m, ans, dfn[maxn], ed, nod; 
    struct node{
    	int u, v, nxt;
    }e[maxn << 1];
    int js, head[maxn];
    void add(int u, int v)
    {
    	e[++js] = (node){u, v, head[u]};
    	head[u] = js;
    }
    void init()
    {
    	js = 0, ans = 1;
    	memset(dfn, 0, sizeof dfn);
    	memset(head, 0, sizeof head);
    }
    queue<int> q;
    int bfs(int s)
    {
    	int sum = 0, flag = 0, nod = 0;
    	q.push(s);
    	dfn[s] = 1;
    	while(!q.empty())
    	{
    		int u = q.front(); q.pop();
    		nod++; 
    		for(int i = head[u]; i; i = e[i].nxt)
    		{
    			sum++;
    			int v = e[i].v;
    			if(v == u) flag = 1; //自环 
    			if(dfn[v]) continue;
    			dfn[v] = 1;
    			q.push(v); 
    		}
    	}
    	sum /= 2;
    	if(sum == nod - 1) return nod;
    	if(sum == nod) return 2 - flag;
    	return 0;
    }
    signed main()
    {
    	//freopen("ball.in", "r", stdin);
    	//freopen("ball.out", "w", stdout);
    	T = read();
    	while(T--)
    	{
    		init();
    		n = read(), m = read();
    		for(int i = 1; i <= n; i++) 
    		{
    			int u = read(), v = read();
    			add(u, v), add(v, u);
    		}
    		for(int i = 1; i <= m; i++) 
    		{
    			if(dfn[i]) continue;
    			ans = ans * bfs(i) % mod;
    		}
    		printf("%lld
    ", ans % mod);
    	}
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    

    T3

    我太菜了。

  • 相关阅读:
    MySql学习
    python学习笔记
    关于字符编码的理解
    session与cookie
    常用的表单元素
    Linq基础
    发送邮件。。
    进程与线程
    winform知识点集合
    winform基础与简单的窗体
  • 原文地址:https://www.cnblogs.com/yangchengcheng/p/15471624.html
Copyright © 2011-2022 走看看