• 2016summer 训练第二场


    1.http://acm.hdu.edu.cn/showproblem.php?pid=5112

    #define _CRT_SECURE_NO_DEPRECATE
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int MAXN = 100000+10;
    struct Node{
    	int t;
    	int x;
    	bool operator<(Node&a){
    		return t < a.t;
    	}
    };
    Node S[MAXN];
    int main(){
    	int i, T,n;
    	int iCase = 1;
    	scanf("%d", &T);
    	while(T--){
    		scanf("%d", &n);
    		for (i = 0; i < n; i++)
    			scanf("%d%d", &S[i].t, &S[i].x);
    		sort(S, S + n);
    		double Max = 0;
    		for (i = 0; i < n - 1; i++){
    			double v = abs(S[i + 1].x - S[i].x)*1.0 / (S[i + 1].t - S[i].t);
    			Max = max(Max, v);
    		}
    		printf("Case #%d: %.2lf
    ",iCase++, Max);
    	}
    	return 0;
    }
    

      2.http://acm.hdu.edu.cn/showproblem.php?pid=5122

    一开始一看到以为求逆序来搞,一看题就写了个数状数组,nlogn超时了。当然一定是太性急了,这个题其实就是判断下它后面是否有数字比它小,有的话需要将其往后移一次,否则不变。这样只需要判断下每个数后面是否有有比它小的数,于是将数组倒置,即为判断每个数前面是否有比它大的数,只需要从前向后扫描一遍,需要一个数Min记录当前已扫描结束的序列中最小的数。这样只要碰到后迷死你右数大于这个最小的数就计数一次,否则更新这个Min。

    #define _CRT_SECURE_NO_DEPRECATE
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int MAXN = 10000001;
    int a[MAXN];
    int main(){
    	int i, T, n;
    	int iCase = 1;
    	scanf("%d", &T);
    	while (T--){
    		scanf("%d", &n);
    		for (i = n; i > 0; i--)
    			scanf("%d", &a[i]);
    		int Min = a[1];
    		int ans = 0;
    		for (i = 2; i <= n; i++){
    			if (a[i] > Min)
    				ans++;
    			else
    				Min = a[i];
    		}
    		printf("Case #%d: %d
    ",iCase++,ans);
    	}
    	return 0;
    }
    

      3.http://acm.hdu.edu.cn/showproblem.php?pid=5120

    模板很重要啊。这里主要的是求两个圆相交的面积,有了模板直接搞。最终面积=大圆交大圆-2*大圆交小圆+小圆交小圆。

    #define _CRT_SECURE_NO_DEPRECATE
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const double EPS = 1e-8;
    const double pi = acos(-1.0);
    struct Point{
    	double x, y;
    	Point(double a=0, double b=0) :x(a), y(b){}
    };
    struct Circle{
    	Circle(Point a, double x) :o(a), r(x){}
    	Point o;
    	double r;
    };
    int RlCmp(double r1, double r2){
    	if (abs(r1 - r2) < EPS)
    		return 0;
    	return r1 < r2 ? -1 : 1;
    }
    Point operator-(Point a, Point b){
    	return Point(a.x - b.x, a.y - b.y);
    }
    Point operator+(Point a, Point b){
    	return Point(a.x + b.x, a.y + b.y);
    }
    double Mold(Point a){
    	return sqrt(a.x*a.x + a.y*a.y);
    }
    double Dis(Point a, Point b){
    	return Mold(a - b);
    }
    //园与圆相交面积模板
    double CircleCrossArea(Circle A,Circle B){
    	double r1 = A.r, r2 = B.r;
    	double d = Dis(A.o, B.o),r=min(r1,r2);
    	if (RlCmp(d, r1 + r2) >= 0)
    		return 0;        //相离或者外切
    	if (RlCmp(d, abs(r1 - r2)) <= 0)
    		return pi*r*r;       //内含
    	//将r1放在圆心
    	double x1 = (d*d + r1*r1 - r2*r2) / (2 * d);
    	double s1 = x1*sqrt(r1*r1 - x1*x1) - r1*r1*acos(x1/r1);
    	//将r2放在圆心
    	double x2 = (d*d + r2*r2 - r1*r1) / (2 * d);
    	double s2 = x2*sqrt(r2*r2 - x2*x2) - r2*r2*acos(x2 / r2);
    	return abs(s1 + s2);
    }
    int main(){
    	int T, iCase = 1;
    	Point q,o;
    	double r1, r2;
    	scanf("%d", &T);
    	while (T--){
    		scanf("%lf%lf",&r1,&r2);
    		scanf("%lf%lf",&q.x,&q.y);
    		scanf("%lf%lf", &o.x,&o.y);
    		Circle A1(q, r1);
    		Circle A2(q, r2);
    		Circle B1(o, r1);
    		Circle B2(o, r2);
    		double a = CircleCrossArea(A2, B2);
    		double b = CircleCrossArea(A2, B1);
    		double c = CircleCrossArea(A1, B1);
    		printf("Case #%d: %.6lf
    ", iCase++, a - 2 * b + c);
    	}
    	return 0;
    }
    

      4.http://acm.hdu.edu.cn/showproblem.php?pid=5113

    一个很好的搜索题。对矩阵从左到右,一行一行的进行搜索(不要把回溯写错或者写漏掉.....老毛病).注意剪枝,一个剪枝条件是,当某一种颜色的数量超过(格子总数+1)/2时,剩下颜色拼出的一定是不合法的。

    #define _CRT_SECURE_NO_DEPRECATE
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int MAXN = 7;
    int a[7][7];
    int b[MAXN*MAXN];
    int k, n, m,iCase;
    int dir[4][2] = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
    bool ans;
    bool isLeg(int x, int y,int val){
    	//判断在a[x][y]处填颜色val是否合法
    	return x - 1 >=0 && a[x - 1][y] != val
    		&&y - 1 >=0 && a[x][y - 1] != val;
    }
    void DFS(int r,int c,int cur){
    	for (int i = 1; i <= k; i++){
    		if (b[i]>(cur+1)/2)   //剪枝
    			return;
    	}
    	if (c > m){
    		c = 1;
    		r++;
    	}
    	if (r > n){   
    		//r>n时,表明已经搜索完成
    		ans = true;
    		printf("Case #%d:
    YES
    ", iCase++);
    		for (int i = 1; i <= n; i++)
    		for (int j = 1; j <= m; j++){
    			printf(j == m ? "%d
    " : "%d ", a[i][j]);
    		}
    	}
    	if (ans)
    		return;
    	for (int i = 1; i <= k; i++){
    		if (b[i] > 0 && isLeg(r, c, i)){
    			a[r][c] = i;
    			b[i]--;
    			DFS(r, c+1,cur-1);
    			//记得回溯洛......
    			b[i]++;
    			a[r][c] = 0;
    		}
    	}
    }
    int main(){
    	int T, i,j;
    	scanf("%d", &T);
    	iCase = 1;
    	while (T--){
    		scanf("%d%d%d", &n, &m,&k);
    		for (i = 1; i <= k; i++)
    			scanf("%d", &b[i]);
    		memset(a, 0, sizeof(a));
    		ans = false;
    		DFS(1, 1,n*m);
    		if (!ans)
    			printf("Case #%d:
    NO
    ", iCase++);
    	}
    	return 0;
    }
    

      5.http://acm.hdu.edu.cn/showproblem.php?pid=5119

    背包问题,真难看出来....。用dp[i][j]表示前i个数中异或值为j的选法数。则得到状态转移方程dp[i][j]=dp[i-1][j]+dp[i-1][j^a[i]];   这里有一个性质:若a^b=c,则b^c=a,a^c=b;题目还有一个坑点,Mi<=10^6,但是他们的异或值可能会超过10^6,于是数组开在10^6大一点不行,但是开在10^7又会爆掉。考虑到10^6的二进制数异或值不会大于2^20次方,从而可以拿这个数来开数组。另外,第i行只与第i-1行有关,可以使用滚动数组。

    #define _CRT_SECURE_NO_DEPRECATE
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    const int MAXN = 1<<20;
    LL n, m;
    LL a[45];
    LL f[2][MAXN];
    int main(){
    	LL i, iCase, T,j;
    	iCase = 1;
    	scanf("%I64d", &T);
    	while (T--){
    		scanf("%I64d%I64d", &n, &m);
    		for (i = 1; i <= n; i++)
    			scanf("%I64d", &a[i]);
    		memset(f, 0, sizeof(f));
    		//从前0个数中选取0个数,异或值等于0,方法有一种,就是什么也不选
    		f[0][0] = 1;
    		for (i = 1; i <= n; i++){
    			for (j=0;j<MAXN; j++){
    					f[i%2][j] = f[(i-1)%2][j] + f[(i-1)%2][j^a[i]];
    			}
    		}
    		LL ans = 1;
    		ans <<= n;
    		for (i =0; i <m;i++)
    			ans-= f[n%2][i];
    		printf("Case #%I64d: %I64d
    ",iCase++,ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    你知道RAID的初始化过程吗?
    Dynamic Disk Pool技术解析
    Ubuntu-16.04.6 安装 oracle 11.2.0.4 数据库database软件
    Ubuntu-16.04.6 安装 oracle 12.2.0.1 数据库database软件
    IDEA 快捷键
    Redis 常用操作命令
    甘特图
    PERT图
    现金贷
    线上信贷提供解决方案
  • 原文地址:https://www.cnblogs.com/td15980891505/p/5757553.html
Copyright © 2020-2023  润新知