Codeforces Round #369 (Div. 2)

A. Bus to Udayland
纯水题不说了、
#include<algorithm>
#include<cmath>
#include<stdio.h>
#include<queue>
#include<stack>
#include<cstring>
#include<string>
#include<iostream>
using namespace std;
const int qq = 1e5+10;
string str[qq];
int main(){
	int n;scanf("%d",&n);
	for(int i=0; i<n; ++i)	cin >> str[i];
	int flag = 0;
	for(int i=0; i<n; ++i){
		if(str[i][0]=='O'&&str[i][1]=='O'){
			flag = 1;
			str[i][0] = str[i][1]='+';
			break;
		}
		else if(str[i][3]=='O'&&str[i][4]=='O'){
			flag = 1;
			str[i][4] = str[i][3]='+';
			break;
		}
	}
	if(!flag)	printf("NO\n");
	else{
		printf("YES\n");
		for(int i=0; i<n; ++i)	cout << str[i] << endl;
	}
	return 0;
}


B. Chris and Magic Square
题意:给一个n*n个矩阵,其中有且又只有一个为0,其他全是正整数要求你在0的位置上填上一个正整数是的每行每列以及两条主要的对角线的和都相等
思路:我是先把元素0所在的行和列排开,先判断剩下的行和列以及对角线是否相等,然后把0所在的行和列以及对角线的和加起来填上一个数看是否相等
(注意这题0的位置一定要填上正整数)

#include<algorithm>
#include<cmath>
#include<stdio.h>
#include<queue>
#include<stack>
#include<cstring>
#include<string>
using namespace std;
typedef __int64 ll;
const int qq = 505;
ll mar[qq][qq];
ll r[qq],c[qq];
ll zero[5];
int main(){
	int n;scanf("%d",&n);
	if(n==1){
		printf("1\n");
		return 0;
	}
	int tx,ty;
	for(int i=1; i<=n; ++i)
		for(int j=1; j<=n; ++j){
			scanf("%I64d",&mar[i][j]);
			if(mar[i][j]==0)	tx=i,ty=j;
		}
	int flag = 1;
	ll tmp;
	for(int i=1; i<=n; ++i)
		if(i!=tx){
			ll sum = 0;
			for(int j=1; j<=n; ++j)
				sum+=mar[i][j];
			r[i] = sum;
			tmp = r[i];
		}
	for(int i=1; i<=n; ++i)
		if(i!=tx&&r[i]!=tmp)	flag = 0;
	for(int j=1; j<=n; ++j)
		if(j!=ty){
			ll sum = 0;
			for(int i=1; i<=n; ++i)
				sum+=mar[i][j];
			c[j] = sum;
		}
	for(int i=1; i<=n; ++i)
		if(i!=ty&&c[i]!=tmp)	flag = 0;
	ll u;
	if(ty!=tx){
		u = 0;
		for(int i=1; i<=n; ++i)
			u+=mar[i][i];
		if(u!=tmp)	flag = 0;
	}
	if(tx!=n-ty+1){
		u = 0;
		for(int i=1; i<=n; ++i)
			u+=mar[i][n-i+1];
		if(u!=tmp)	flag = 0;
	}
	if(!flag){
		printf("-1\n");
		return 0;
	}
	for(int j=1; j<=n; ++j)
		zero[0]+=mar[tx][j];
	for(int i=1; i<=n; ++i)
		zero[1]+=mar[i][ty];
	int k=2;
	if(tx==ty){
		for(int i=1; i<=n; ++i)
			zero[k]+=mar[i][i];
		k++;
	}
	if(tx+ty==n+1){
		for(int i=1; i<=n; ++i)
			zero[k]+=mar[i][n+1-i];
		k++;
	}
	ll d = tmp-zero[0];
	if(d<=0){
		printf("-1\n");
		return 0;
	}
	for(int i=1; i<k; ++i){
		if(d!=tmp-zero[i])	flag = 0;
	}	
	if(!flag)	printf("-1\n");
	else	printf("%I64d\n", d);
	return 0;
}

正解的做法应该是在0的位置上先填上一个数在判断矩阵是否合法、这样代码量就少很多、

还有我阿,特别粗心,首先没注意一定正整数,另外我在判断行和列的时候没有判断对角线。。。


C. Coloring Trees

题意:有n颗树,每一颗数上都有一个数值,0代表这个数还没涂上颜色,tree[i]>0代表这个数的颜色为tree[i],给出n,m,k,m代表有多少中颜色可以用编号是1到m,k代表魅力值为k,美丽值是这样定义的连续的一段相同的颜色的树美丽值为1,然后叠加就成了n课树的美丽值,最后给出n棵树涂上1到m中每种颜色的energy,求最小的eremgy

思路:n棵树n种美丽值m种颜色,定义状态dp[i][j][k] 前i棵树美丽值为j且第i棵树颜色为k的时候的最小energy

那么当第i棵树的颜色和第i-1棵树的颜色不同时 dp[i][j+1][k] = min(dp[i][j+1][k], dp[i-1][j][l]+color[i][k])

颜色相同时  dp[i][j][k] = min(dp[i][j][k], dp[i-1][j][l])

这里只是简单的分析,还要讨论第i课树是否为有颜色然后再去转移状态

有颜色的数不需要再计算energy,只需要求出没有颜色的树涂上颜色的最小energy

#include<algorithm>
#include<cmath>
#include<stdio.h>
#include<queue>
#include<stack>
#include<cstring>
#include<string>
using namespace std;
typedef __int64 ll;
const int qq = 100+5;
const ll MAX = 1e16 + 10;
int tree[qq];
int color[qq][qq];
ll dp[qq][qq][qq];	//dp[i][j][k]´ú±íÇ°i¿ÃÊ÷ÃÀÀöֵΪjÇÒµÚi¿ÃÊ÷ÑÕɫΪkµÄʱºòµÄ×îСenergy¡¢ 
int main(){
	int n,m,k;scanf("%d%d%d",&n,&m,&k);
	for(int i=1; i<=n; ++i)	scanf("%d",&tree[i]);
	for(int i=1; i<=n; ++i)
		for(int j=1; j<=m; ++j)
			scanf("%d",&color[i][j]);
	for(int i=1; i<=n; ++i)
		for(int j=1; j<=n; ++j)
			for(int l=1; l<=m; ++l)
				dp[i][j][l] = MAX;
	if(tree[1])	dp[1][1][tree[1]] = 0;
	else	for(int i=1; i<=m; ++i)	dp[1][1][i]=color[1][i];
	for(int i=2; i<=n; ++i)
		if(!tree[i]){
			for(int j=1; j<i; ++j)
				for(int l=1; l<=m; ++l)
					for(int c=1; c<=m; ++c)
						if(l!=c)	dp[i][j+1][c]=min(dp[i][j+1][c], dp[i-1][j][l]+color[i][c]);
						else	dp[i][j][c]=min(dp[i][j][c], dp[i-1][j][l]+color[i][c]);
		}
		else{
			for(int j=1; j<i; ++j)
				for(int l=1; l<=m; ++l)
					if(l!=tree[i])	dp[i][j+1][tree[i]]=min(dp[i][j+1][tree[i]], dp[i-1][j][l]);
					else	dp[i][j][tree[i]]=min(dp[i][j][tree[i]], dp[i-1][j][l]);
		}
	ll ans = MAX;
	for(int i=1; i<=m; ++i)
		ans=min(ans, dp[n][k][i]);
	if(ans==MAX)	ans = -1;
	printf("%I64d\n",ans);
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值