Codeforces Round #277 (Div. 2) 解题报告(B C)

B. OR in Matrix


        题意:一个“逻辑或”矩阵,他每个元素的值是原矩阵对应行列所有值逻辑或起来的结果,给出或矩阵,问是否存在原矩阵。

        思路:如果或矩阵某个元素为0,原矩阵的对应行/列都只能是0。构造一下就好了。

#include<iostream>      
#include<cmath>      
#include<cstring>      
#include<queue>      
#include<vector>      
#include<algorithm>      
#include<string.h>      
#include<cstdio>      
      
using namespace std;

int mp[110][110];
bool nn[110];
bool mm[110];
int ans[110][110];

int main(){
	int m,n;
	while(cin>>n>>m){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				cin>>mp[i][j];
			}
		}
		
		int cntn=0;
		int cntm=0;
		for(int i=1;i<=n;i++){
			bool ok=1;
			for(int j=1;j<=m;j++){
				if(!mp[i][j])ok=0;
			}
			if(ok){
				cntn++;
				nn[i]=1;
			}
		}
		//
		for(int j=1;j<=m;j++){
			bool ok=1;
			for(int i=1;i<=n;i++){
				if(!mp[i][j])ok=0;
			}
			if(ok){
				cntm++;
				mm[j]=1;
			}
		}
		
		bool hasans=1;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				if( mp[i][j] ){
					if( (!nn[i])&&(!mm[j]) )hasans=0;
					if( nn[i]&&mm[j] )ans[i][j]=1;
				}
			}
		}
		if((cntn>0&&cntm==0)||(cntm>0&&cntn==0))hasans=0;
		if(hasans){
			cout<<"YES"<<endl;
			for(int i=1;i<=n;i++){
				for(int j=1;j<=m;j++){
					cout<<ans[i][j];
					if(j!=m)cout<<" ";
				}
				cout<<endl;
			}
		}else{
			cout<<"NO"<<endl;
		}
	}
	return 0;
}


C. Palindrome Transformation


        题意:一个串,需要把它弄成回文串。有一个指针,上下移动能循环改变对应位置字符的值,左右移动能改变指针位置。问最少多少次操作变成回文。

        思路:可以把串分为左右两部分,改变左右的结果是一样的,也就是说如果指针初始在左边,就没必要跑右边去。最少改变次数就是左右移动次数+上下移动次数。见代码注释。

#include<iostream>      
#include<cmath>      
#include<cstring>      
#include<queue>      
#include<vector>      
#include<algorithm>      
#include<string.h>      
#include<cstdio>      
      
using namespace std;

char str[100010];
int d[100010];

int main(){
	int n,p;
	while(cin>>n>>p){
		scanf("%s",str+1);
		memset(d,0,sizeof(d));
		int L,R;
		if(n&1){
			L=n/2;
			R=L+2;
		}else{
			L=n/2;
			R=L+1;
		}
		
		//计算上下移动次数 
		int sum=0;
		for(;L>=1;L--,R++){
			d[L]=d[R]=min( abs(str[R]+26-str[L]) ,min( abs(str[L]+26-str[R]) , abs(str[L]-str[R]) ) );
			
			sum+=d[L];
		}
		if(sum==0){
			cout<<0<<endl;
			continue;
		}
		
		//如果指针在右边,直接放到左边对称位置 
		if(p>n/2){
			p=n-p+1;
		}
		
		//计算左右移动次数(利用需要修改的范围) 
		int lmost=1;
		int rmost=n/2; 
		for(;;lmost++)if(d[lmost])break;
		for(;;rmost--)if(d[rmost])break;
		
		if(p<=lmost){
			cout<<sum+rmost-p<<endl;;
		}else if(p>=rmost){
			cout<<sum+p-lmost<<endl;
		}else{
			int tmp=min(p-lmost,rmost-p);
			cout<<sum+tmp+rmost-lmost<<endl;
		}
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值