CSP 2015-12

1.数位和

#include<iostream>
using namespace std;

int main(){
	char c;
	int ans=0;
	while(cin.get(c)){
		if(c=='\n') break;
		ans+=c-'0';
	}	
	cout<<ans;
}

2.消除游戏

#include<iostream>
using namespace std;
//思路:对于每一个棋子,判断其是否可以被消掉,将要被消除的点进行标记,待遍历完毕后记为0
// 如何判断? 找到该棋子左右上下的边界即可,判断边界大小是否大于等于3 
#define N 40
struct node{
	int c,v;
}a[N][N];
int n,m;

bool could_del(int x,int y){
	int u,d,r,l;
	for(u=x;u>=0&&a[u][y].c==a[x][y].c;u--);
	for(d=x;d<n&&a[d][y].c==a[x][y].c;d++);
	for(r=y;r<m&&a[x][r].c==a[x][y].c;r++);
	for(l=y;l>=0&&a[x][l].c==a[x][y].c;l--);
	return d-u>=4||r-l>=4;	
}

int main(){
	cin>>n>>m;
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			cin>>a[i][j].c,a[i][j].v=0;
	
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++)
			{
			if(could_del(i,j)) cout<<0<<" ";
			else cout<<a[i][j].c<<" ";
			}
			cout<<endl;
			}
}

3.画图
直接模拟就可以:但是这个题有两个坑

  • 数学坐标系写代码太麻烦了
    -如果之前的字符是’+‘的话,那么经过画线过后不应该被覆盖为’-‘或者’|’,不然只能拿90分
#include<iostream>
#include<algorithm>
using namespace std;
#define N 110
char a[N][N];
int n,m,q;

void _line(int x1,int y1,int x2,int y2){
	if(x1==x2){
		int ymax=max(y1,y2);
		int ymin=min(y1,y2);
		for(int i=ymin;i<=ymax;i++){
			if(a[x1][i]=='-'||a[x1][i]=='+') a[x1][i]='+';
			else a[x1][i]='|';
		}
	}else{
		int xmax=max(x1,x2);
		int xmin=min(x1,x2);
		for(int i=xmin;i<=xmax;i++){
			if(a[i][y1]=='|'||a[i][y1]=='+') a[i][y1]='+';
			else a[i][y1]='-';
		}
	}
}

int dir[][2]={0,1,0,-1,1,0,-1,0};

void _fill(int x,int y,char c){
	if(a[x][y]==c) return ;
	a[x][y]=c;
	for(int i=0;i<4;i++){
		int nx=x+dir[i][0];
		int ny=y+dir[i][1];
		if(nx<0||nx>=m||ny<0||ny>=n) continue;
		if(a[nx][ny]=='|'||a[nx][ny]=='-'||a[nx][ny]=='+') continue;
		_fill(nx,ny,c);
	}
}

int main(){
		cin>>m>>n>>q;
		_fill(0,0,'.');
		while(q--){
			int o;
			cin>>o;
			if(o){
				int x,y;
				char c;
				cin>>x>>y>>c;
				_fill(x,y,c);
			}else{
				int x1,y1,x2,y2;
				cin>>x1>>y1>>x2>>y2;
				_line(x1,y1,x2,y2);
			}
		}

		for(int j=n-1;j>=0;j--){
			for(int i=0;i<m;i++)
			putchar(a[i][j]);
			putchar('\n');
		}
			
}

4.送货:
自己的代码:

#include<iostream>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
#define N 10010
//统计奇点个数,若1不是奇点,则无解,若奇点个数不为2也无解
//dfs求解即可 
set<int> G[N];
int n,m;
vector<int> res;
void dfs(int k){ //当前的位置在k
	if(!G[k].size()) return ; 
	int nxt=*G[k].begin();
	res.push_back(nxt);
	G[k].erase(nxt);
	G[nxt].erase(k);
	dfs(nxt);
}
int main(){
	cin>>n>>m;
	int k=m;
	while(m--){
		int a,b;
		cin>>a>>b;
		G[a].insert(b);
		G[b].insert(a);
	}
		
	if(G[1].size()%2==0) {
		cout<<"-1";
		return 0;
	}
	
	int cnt=0;
	for(int i=1;i<=n;i++)
	cnt+=(G[i].size()%2);
	
	if(cnt!=2&&cnt!=0){ //若没有奇点,则回路为从A出发,从A结束 
		cout<<"-1";
		return 0;
	}
	
	dfs(1);

	if(res.size()!=k) {
		cout<<"-1";
		return 0;
	}
	 
	cout<<1<<" ";
	for(int i=0;i<res.size();i++)
	cout<<res[i]<<" ";
}
	

错的,只有10分,分析为什么错了:

  • 在判断奇点个数时候出错了:
    正确的判断代码应该是:

	if(cnt!=2&&cnt!=0||(cnt==2&&G[1].size()%2!=1)){  
		cout<<"-1";
		return 0;
	}
  • 是因为没有用并查集判断连通性吗?
    不是,如果图是联通的,那么进行dfs后得到的vector大小一定和m相同

  • 正解,dfs函数出错,在遍历时候每次都只取该点的一条边,若该点是奇点就出错了
    正确的dfs代码如下: (至于为什么要回溯再记录,我也不清楚)

void dfs(int k){ //当前的位置在k
	while(G[k].size()){
		int t=*G[k].begin();
		G[k].erase(t);
		G[t].erase(k);
		dfs(t);
	}
	res.push_back(k);
}

y总完整代码如下:

#include<iostream>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
#define N 10010
//统计奇点个数,若1不是奇点,则无解,若奇点个数不为2也无解
//dfs求解即可 
set<int> G[N];
int n,m;
vector<int> res;
void dfs(int k){ //当前的位置在k
	while(G[k].size()){
		int t=*G[k].begin();
		G[k].erase(t);
		G[t].erase(k);
		dfs(t);
	}
	res.push_back(k);
}
int main(){
	cin>>n>>m;
	int k=m;
	while(m--){
		int a,b;
		cin>>a>>b;
		G[a].insert(b);
		G[b].insert(a);
	}
	
	int cnt=0;
	for(int i=1;i<=n;i++)
	cnt+=(G[i].size()%2);
	
	if(cnt!=2&&cnt!=0||(cnt==2&&G[1].size()%2!=1)){  
		cout<<"-1";
		return 0;
	}
	
	dfs(1);

	if(res.size()!=k+1) {
		cout<<"-1";
		return 0;
	}
	 //记得要倒着输出,因为答案也是倒着记录的
	for(int i=res.size()-1;i>=0;i--)
	cout<<res[i]<<" ";
}
	

5.第五题不会

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值