zoukankan      html  css  js  c++  java
  • Dhaka2011

    Dhaka2011

    A - Binary Matrix

    题目描述:有一个(n imes m)(01)矩阵,这一矩阵第一行和最后一行是相邻的,第一列和最后一列是相邻的,现在每次可以交换相邻的两个位置的数(四相邻),问最少多少次操作使得每一行的(1)的个数相同,每一列的(1)的个数相同,如果不行,则最少多少次操作使得每一行的(1)的个数相同,如果不行,则最少多少次操作使得每一列的(1)的个数相同,如果不行,则输出无解。

    solution
    行和列是独立的,因此可以分开做,由于矩阵第一行和最后一行是相邻的,因此要枚举第一行,然后按顺序填补,多则出,少则进,然后取最小值即可。

    时间复杂度:(O(n^2+m^2))

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long LL;
    const LL inf=1LL<<60;
    const int maxn=1010;
    
    int n, m, total;
    int row[maxn], col[maxn];
    
    void read()
    {
    	scanf("%d%d", &n, &m);
    	for (int i=1; i<=n; ++i) row[i]=0;
    	for (int i=1; i<=m; ++i) col[i]=0;
    	for (int i=1; i<=n; ++i)
    		for (int j=1; j<=m; ++j)
    		{
    			int x;
    			scanf("%1d", &x);
    			row[i]+=x; col[j]+=x;
    		}
    }
    LL work(int n, int *a)
    {
    	LL ans=inf;
    	int each=total/n;
    	for (int i=1; i<=n; ++i)
    	{
    		int rest=0;
    		LL s=0;
    		int cur=i;
    		for (int j=1; j<=n; ++j, cur=(cur==n? 1:cur+1))
    		{
    			if (a[cur]>each)
    			{
    				if (rest<0)
    				{
    					int used=min(-rest, a[cur]-each);
    					s+=used*j; rest+=a[cur]-each;
    					s-=(a[cur]-each-used)*j;
    				}
    				else { s-=(a[cur]-each)*j; rest+=a[cur]-each; }
    			}
    			else
    			{
    				if (rest>0)
    				{
    					int used=min(rest, each-a[cur]);
    					s+=used*j; rest-=each-a[cur];
    					s-=(each-a[cur]-used)*j;
    				}
    				else { s-=(each-a[cur])*j; rest-=each-a[cur]; }
    			}
    		}
    		ans=min(ans, s);
    	}
    	return ans;
    }
    void solve()
    {
    	total=0;
    	for (int i=1; i<=n; ++i) total+=row[i];
    	if (total%n==0 && total%m==0) printf("both ");
    	else if (total%n==0) printf("row ");
    	else if (total%m==0) printf("column ");
    	else { puts("impossible"); return; }
    
    	LL ans=0;
    	if (total%n==0) ans+=work(n, row);
    	if (total%m==0) ans+=work(m, col);
    	printf("%lld
    ", ans);
    }
    int main()
    {
    	int casesum;
    	scanf("%d", &casesum);
    	for (int i=1; i<=casesum; ++i)
    	{
    		printf("Case %d: ", i);
    		read();
    		solve();
    	}
    	return 0;
    }
    

    B - Candles

    solution

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long LL;
    
    int n;
    int a[20], idx[1<<10];
    bool flag[1<<10][210];
    LL num[1<<10];
    
    bool cmp(int b, int c)
    {
    	return num[b]<num[c];
    }
    void init()
    {
    	for (int sett=0; sett<1<<10; ++sett)
    	{
    		int cnt=0;
    		for (int i=0; i<10; ++i)
    			if (sett>>i & 1) a[++cnt]=i;
    		num[sett]=0;
    		for (int i=cnt; i; --i) num[sett]=num[sett]*10+a[i];
    
    		for (int i=1; i<=cnt; ++i)
    		{
    			flag[sett][a[i]]=true;
    			for (int j=1; j<=cnt; ++j)
    				if (i!=j)
    				{
    					flag[sett][a[i]*10+a[j]]=true;
    					flag[sett][a[i]+a[j]]=true;
    					for (int k=1; k<=cnt; ++k)
    						if (i!=k && j!=k)
    						{
    							flag[sett][a[i]*10+a[j]+a[k]]=true;
    							for (int p=1; p<=cnt; ++p)
    								if (i!=p && j!=p && k!=p)
    									flag[sett][a[i]*10+a[j]+a[k]*10+a[p]]=true;
    						}
    				}
    		}
    	}
    	for (int i=0; i<1<<10; ++i) idx[i]=i;
    	sort(idx, idx+(1<<10), cmp);
    }
    bool read()
    {
    	scanf("%d", &n);
    	for (int i=1; i<=n; ++i) scanf("%d", &a[i]);
    	return n;
    }
    void solve()
    {
    	for (int i=0; i<1<<10; ++i)
    	{
    		bool can=true;
    		for (int j=1; j<=n && can; ++j) can&=flag[idx[i]][a[j]];
    		if (can)
    		{
    			printf("%lld
    ", num[idx[i]]);
    			return;
    		}
    	}
    }
    int main()
    {
    	init();
    	int casesum=0;
    	while (read())
    	{
    		printf("Case %d: ", ++casesum);
    		solve();
    	}
    	return 0;
    }
    

    C - Cards

    题目描述:一副(54)张的扑克牌,随机排序,按顺序抽取,抽到大小王可以让他们变成任意一种花色(要当场决定),问期望抽多少张牌使得每种花色至少有(A, B, C, D)张。

    solution
    概率(dp),思路挺好想的,就记住每种花色剩下多少张,以及每个王变成了什么花色(或者还没抽到)

    时间复杂度:(O(13^4*5^2*4))(每次询问)

    G - Pair of Touching Circles

    题目描述:给定一个(n imes m)的网格图,在图中画两个圆,要求者两个圆的圆心要在格点上,半径要是整数(两个圆的半径不一定相等),整个圆要在网格图内,两个圆要相切,问方案数。

    solution
    先预处理出两个圆所形成的矩形的情况,以及每种情况对应的方案数,然后问题就变成了给定的网格图每种矩形有多少个。
    预处理这部分可以枚举两个圆心横坐标的差以及纵坐标的差,判断是否能相切(其实就是判勾股数),然后再枚举其中一个圆的半径,就可以算出两个圆所对应的矩形,然后统计结果。

    时间复杂度:(O(能过))(因为勾股数不多)

    H - Treasure Hunt

    题目描述:在二维平面上,给出一个矩形的顶点坐标,在给定在矩形内的四个点,问这四个点要如何移动,使得移动后四个点的重心与矩形重心重合,并且移动的距离总和最小,求移动后的坐标。

    solution
    可以先把矩形的重心移到原点,然后算出四个点的重心,重心指向原点的向量就是四个点的移动的向量的总和,因为要移动的距离总和最小,因此所有点的移动的向量应与重心指向原点的向量平行,然后逐个移动即可。

    时间复杂度:(O(1))

    #include <bits/stdc++.h>
    using namespace std;
    
    #define x first
    #define y second
    typedef long double LD;
    const LD eps=1e-15;
    const LD inf=1e18;
    
    struct Point:public pair<LD, LD>
    {
    
    	Point(LD _x=0, LD _y=0):pair(_x, _y){}
    
    	Point& operator += (Point c)
    	{
    		x+=c.x; y+=c.y;
    		return *this;
    	}
    
    	Point& operator /= (LD c)
    	{
    		x/=c; y/=c;
    		return *this;
    	}
    
    	Point& operator -= (Point c)
    	{
    		x-=c.x; y-=c.y;
    		return *this;
    	}
    
    	Point operator + (Point c)
    	{
    		return Point(x+c.x, y+c.y);
    	}
    
    	Point operator - (Point c)
    	{
    		return Point(x-c.x, y-c.y);
    	}
    
    	Point operator * (LD c)
    	{
    		return Point(x*c, y*c);
    	}
    
    	Point operator / (LD c)
    	{
    		return Point(x/c, y/c);
    	}
    
    	bool zero()
    	{
    		return (fabs(x)<eps && fabs(x)<eps);
    	}
    
    	void rotate(LD angle)
    	{
    		LD tmp=x;
    		x=-sin(angle)*y+cos(angle)*tmp;
    		y=sin(angle)*tmp+cos(angle)*y;
    	}
    };
    
    Point origin;
    LD angle;
    Point pos[10], rec[10], ans[10];
    
    inline LD sqr(LD x)
    {
    	return x*x;
    }
    LD dis(Point b, Point c)
    {
    	return sqrt(sqr(b.x-c.x)+sqr(b.y-c.y));
    }
    bool read()
    {
    	for (int i=1; i<=4; ++i) scanf("%Lf%Lf", &pos[i].x, &pos[i].y);
    	for (int i=1; i<=4; ++i) scanf("%Lf%Lf", &rec[i].x, &rec[i].y);
    	for (int i=1; i<=4; ++i)
    		if (fabs(pos[i].x)>eps || fabs(pos[i].y)>eps) return true;
    	for (int i=1; i<=4; ++i)
    		if (fabs(rec[i].x)>eps || fabs(rec[i].y)>eps) return true;
    	return false;
    }
    void rotate()
    {
    	origin=Point(0, 0);
    	for (int i=1; i<=4; ++i) origin+=rec[i];
    	origin/=4;
    	for (int i=1; i<=4; ++i)
    	{
    		rec[i]-=origin;
    		pos[i]-=origin;
    	}
    	Point arrow=rec[2]-rec[1];
    	angle=atan2(arrow.y, arrow.x);
    	for (int i=1; i<=4; ++i)
    	{
    		rec[i].rotate(-angle);
    		pos[i].rotate(-angle);
    	}
    }
    void solve()
    {
    	rotate();
    	Point total=Point(0, 0);
    	Point boundx=Point(inf, -inf), boundy=Point(inf, -inf);
    	for (int i=1; i<=4; ++i) total-=pos[i];
    	for (int i=1; i<=4; ++i)
    	{
    		boundx.x=min(rec[i].x, boundx.x);
    		boundx.y=max(rec[i].x, boundx.y);
    		boundy.x=min(rec[i].y, boundy.x);
    		boundy.y=max(rec[i].y, boundy.y);
    	}
    
    	LD answer=0;
    	for (int i=1; i<=4; ++i)
    	{
    		Point bound=Point((total.x<0? boundx.x:boundx.y), (total.y<0? boundy.x:boundy.y));
    		Point tmp=bound-pos[i];
    		LD rate=min(LD(1.0), min(tmp.x/total.x, tmp.y/total.y));
    		tmp=pos[i]+total*rate;
    		total-=tmp-pos[i];
    		answer+=dis(pos[i], tmp);
    		pos[i]=tmp;
    	}
    
    	for (int i=1; i<=4; ++i)
    	{
    		pos[i].rotate(angle);
    		pos[i]+=origin;
    	}
    	for (int i=1; i<=4; ++i) printf("%.12Lf %.12Lf
    ", pos[i].x, pos[i].y);
    	puts("");
    }
    void readans()
    {
    	for (int i=1; i<=4; ++i) scanf("%Lf%Lf", &ans[i].x, &ans[i].y);
    	LD answer=0;
    	for (int i=1; i<=4; ++i) answer+=dis(ans[i], pos[i]);
    	printf("%.12Lf
    ", answer);
    }
    int main()
    {
    	while (read()) solve();
    	return 0;
    }
    

    I - Truchet Tiling

    题目描述:有两种(2 imes 2)的地砖,如图,现在有(n imes m)块地砖拼在一起,以圆弧连成的线作为分界进行涂色,给出一些询问,每次给定一个坐标,问该坐标所在的区域的面积。

    solution
    将一块地砖分成三个区域,然后题目的意思做并查集,再处理出每个坐标所在的并查集。

    时间复杂度:(O(nm))

    #include <bits/stdc++.h>
    using namespace std;
    
    const double PI=acos(-1);
    const int maxn=110;
    
    int n, m;
    int dsu[maxn*maxn*4];
    double area[maxn*maxn*4];
    bool Map[maxn][maxn];
    int pos[maxn*2][maxn*2];
    
    void read()
    {
    	scanf("%d%d", &n, &m);
    	for (int i=1; i<=n*m*3; i+=3) 
    	{
    		dsu[i]=dsu[i+1]=dsu[i+2]=-1;
    		area[i]=area[i+2]=PI/4;
    		area[i+1]=2*2-PI/2;
    	}
    	for (int i=1; i<=n; ++i)
    		for (int j=1; j<=m; ++j)
    			scanf("%1d", &Map[i][j]);
    }
    int dsu_find(int cur)
    {
    	return (dsu[cur]<0? cur:(dsu[cur]=dsu_find(dsu[cur])));
    }
    void merge(int u, int v)
    {
    	u=dsu_find(u);
    	v=dsu_find(v);
    	if (u==v) return;
    	if (dsu[u]>dsu[v]) swap(u, v);
    	dsu[u]+=dsu[v];
    	dsu[v]=u;
    	area[u]+=area[v];
    }
    void divide()
    {
    	for (int i=1; i<=n; ++i)
    		for (int j=1; j<=m; ++j)
    		{
    			int cur=((i-1)*m+j-1)*3;
    			if (i!=1)
    			{
    				int nx=((i-2)*m+j-1)*3;
    				if (Map[i][j]==Map[i-1][j])
    				{
    					merge(nx+2, cur+1);
    					merge(nx+3, cur+2);
    				}
    				else
    				{
    					merge(nx+3, cur+1);
    					merge(nx+2, cur+2);
    				}
    			}
    			if (j!=1)
    			{
    				int nx=((i-1)*m+j-2)*3;
    				if (Map[i][j])
    				{
    					if (Map[i][j-1])
    					{
    						merge(nx+1, cur+2);
    						merge(nx+2, cur+3);
    					}
    					else
    					{
    						merge(nx+2, cur+2);
    						merge(nx+3, cur+3);
    					}
    				}
    				else
    				{
    					if (Map[i][j-1])
    					{
    						merge(nx+1, cur+1);
    						merge(nx+2, cur+2);
    					}
    					else
    					{
    						merge(nx+2, cur+1);
    						merge(nx+3, cur+2);
    					}
    				}
    			}
    		}
    }
    void calc_pos()
    {
    	for (int i=1; i<=n; ++i)
    		for (int j=1; j<=m; ++j)
    		{
    			pos[(i-1)*2][j*2-1]=pos[i*2-1][(j-1)*2]=pos[i*2-1][j*2]=pos[i*2][j*2-1]=0;
    			if (Map[i][j])
    			{
    				pos[(i-1)*2][j*2]=((i-1)*m+j-1)*3+1;
    				pos[(i-1)*2][(j-1)*2]=pos[i*2-1][j*2-1]=pos[i*2][j*2]=((i-1)*m+j-1)*3+2;
    				pos[i*2][(j-1)*2]=((i-1)*m+j)*3;
    			}
    			else
    			{
    				pos[(i-1)*2][(j-1)*2]=((i-1)*m+j-1)*3+1;
    				pos[(i-1)*2][j*2]=pos[i*2-1][j*2-1]=pos[i*2][(j-1)*2]=((i-1)*m+j-1)*3+2;
    				pos[i*2][j*2]=((i-1)*m+j)*3;
    			}
    		}
    		/*
    	for (int i=0; i<=n*2; ++i, putchar('
    '))
    		for (int j=0; j<=m*2; ++j)
    			printf("%d ", pos[i][j]);
    			*/
    }
    void solve()
    {
    	calc_pos();
    	divide();
    	int T;
    	scanf("%d", &T);
    	while (T--)
    	{
    		int x, y;
    		scanf("%d%d", &x, &y);
    		if (pos[x][y]==0) printf("%.4lf
    ", 0.0);
    		else printf("%.4lf
    ", area[dsu_find(pos[x][y])]);
    	}
    }
    int main()
    {
    	int casesum;
    	scanf("%d", &casesum);
    	for (int i=1; i<=casesum; ++i)
    	{
    		printf("Case %d:
    ", i);
    		read();
    		solve();
    	}
    	return 0;
    }
    

    J - As Long as I Learn, I Live

    solution
    模拟。

    时间复杂度:(O(m))

  • 相关阅读:
    JS BOM对象 History对象 Location对象
    JS 字符串对象 数组对象 函数对象 函数作用域
    JS 引入方式 基本数据类型 运算符 控制语句 循环 异常
    Pycharm Html CSS JS 快捷方式创建元素
    CSS 内外边距 float positio属性
    CSS 颜色 字体 背景 文本 边框 列表 display属性
    【Android】RxJava的使用(三)转换——map、flatMap
    【Android】RxJava的使用(二)Action
    【Android】RxJava的使用(一)基本用法
    【Android】Retrofit 2.0 的使用
  • 原文地址:https://www.cnblogs.com/GerynOhenz/p/9893238.html
Copyright © 2011-2022 走看看