Codeforces Round #303 (Div. 2)

A.Toy Cars

原题:http://codeforces.com/contest/545/problem/A

题意:

有n辆车,给出n*n的矩阵;

a[i][j] = 1表示第i辆车坏, = 2表示第j辆车坏,  = 3表示第i, j辆车都坏;

问好的车有几辆;


#include<stdio.h>
#include<string.h>
int n;
int arr[110][110], ans[110];
bool res[110];

int main()
{
	while(scanf("%d", &n)!=EOF)
	{
		int sum = 0;
		memset(res, false, sizeof res);
		for(int i = 1;i<=n;i++)
		{
			for(int j = 1;j<=n;j++)
			{
				scanf("%d", &arr[i][j]);
				if(arr[i][j] == 1)
					res[i] = true;
				if(arr[i][j] == 2)
					res[j] = true;
				if(arr[i][j] == 3)
				{
					res[i] = true;
					res[j] = true;
				}
			}
		}
		int k = 0;
		for(int i = 1;i<=n;i++)
		{
			if(!res[i])
			{
				sum++;
				ans[k++] = i;
			}
		}
		printf("%d\n", sum);
		for(int i = 0;i<k;i++)
		{
			if(i == k-1)
			printf("%d\n", ans[i]);
			else
			printf("%d ", ans[i]);
		}
	}
	return 0;
}




B.Equidistant String

题意:有s1、s2两个字符串,均由01构成;
问能否得到第三个01串c,使得它和给定的两个字符串差值相等,输出满足条件的任意答案即可;
所谓的差值就是各位上的差之和;

思路:
先比较s1、s2,计算两者不同的位置有几个,若是奇数,直接输出impossible;
将不同的位置的个数对半分,在c中,前一半输出s1[i],后一半输出s2[i];



#include<stdio.h>
#include<string.h>
char s1[100005];
char s2[100005];

int main()
{
	while(scanf("%s%s", s1, s2)!=EOF)
	{
		int len = strlen(s1);
		int sum = 0;
		for(int i = 0;i<len;i++)
		{
			if(s1[i]!=s2[i])
			sum++;
		}
		if(sum%2 == 1)	printf("impossible\n");
		else
		{
			sum/=2;
			for(int i = 0;i<len;i++)
			{
				if(s1[i]!=s2[i])
				{
					if(sum)
					{
						printf("%c", s1[i]);
						sum--;
					}
					else
					printf("%c", s2[i]);
				}
				else	printf("%c", s1[i]);
			}
			printf("\n");
		}
	}
	return 0;
}




C.Woodcutters


题意:
给出n棵树的位置x和高度h;
每棵树可以往右倒或者往左倒,但区间必须大于树的高度;
问最多可以砍到几棵树;

思路:
第一棵树肯定往左倒;其他的树左右区间判断一下;


#include<stdio.h>
int n;

struct node
{
	int x, h;
}tree[100005];

int main()
{
	while(scanf("%d", &n)!=EOF)
	{
		int sum;
		if(n>=2)	sum = 2;
		else	sum = 1;
		for(int i = 1;i<=n;i++)
		scanf("%d%d", &tree[i].x, &tree[i].h);
		for(int i = 2;i<n;i++)
		{
			int l1 = tree[i].x-tree[i-1].x;
			int l2 = tree[i+1].x-tree[i].x;
			if(tree[i].h<l1)
				sum++;
			else
			{
				if(tree[i].h<l2)
				{
					sum++;
					tree[i].x+=tree[i].h;<span style="white-space:pre">	</span>//如果向右倒,区间值相应的要改变;
				}
			}
		}
		printf("%d\n", sum);
	}
	return 0;
}



D.Queue

题意:
给出n个人的服务时间;
如果某人的等待时间超过服务时间就不能让该人满意;
问一共可以让多少人满意;

思路:
排序,然后时间累加判断;


#include<stdio.h>
#include<algorithm>

using namespace std;
int n;
int arr[100005];

int main()
{
	while(scanf("%d", &n)!=EOF)
	{
		for(int i = 0;i<n;i++)
		scanf("%d", &arr[i]);
		sort(arr, arr+n);
		int sum = 0;
		int ans = 0;
		for(int i = 0;i<n;i++)
		{
			if(arr[i]>=sum)
			{
				sum+=arr[i];
				ans++;
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}



E.Paths and Trees


题意:
给定一个带权无向图;
选取一些边建立一个新图(节点不变),使得起点st到其他点的距离最短,当最短路相同时选择权值小的边;

思路:
用spfa 跑最短路,当最短距离一样时比较边权;



#include<stdio.h>
#include<queue>
#include<string.h>
#include<algorithm>

using namespace std;
typedef long long ll;
const int maxn = 300005;
const ll inf = 1e16;
int n, m, st;
bool vis[maxn];
int num, head[maxn];
int pre[maxn], val[maxn];<span style="white-space:pre">	</span>//pre[]记录选择的边,val[]记录每条边的权值;
ll dis[maxn];

struct node
{
	int v, w, id, next;
}edge[maxn<<1];

void init()
{
	num = 0;
	memset(head, -1, sizeof head);
}

void add(int u, int v, int w, int id)
{
	edge[num].v = v;
	edge[num].w = w;
	edge[num].id = id;
	edge[num].next = head[u];
	head[u] = num++;
}

void spfa()
{
	queue<int>Q;
	for(int i = 1;i<=n;i++)
	dis[i] = inf;
	memset(vis, false, sizeof vis);
	memset(pre, 0, sizeof pre);
	dis[st] = 0, vis[st] = true;
	Q.push(st);
	while(!Q.empty())
	{
		int u = Q.front();	Q.pop();
		vis[u] = false;
		for(int i = head[u];i!=-1;i = edge[i].next)
		{
			int v = edge[i].v;
			if(dis[v]>dis[u]+edge[i].w)
			{
				dis[v] = dis[u]+edge[i].w;
				pre[v] = edge[i].id;
				if(!vis[v])
				{
					vis[v] = true;
					Q.push(v);
				}
			}
			else if(dis[v] == dis[u]+edge[i].w)
			{
				if(edge[i].w<val[pre[v]])
				{
					pre[v] = edge[i].id;
					if(!vis[v])
					{
						vis[v] = true;
						Q.push(v);
					}
				}
			}
		}
	}
}

int main()
{
	while(scanf("%d%d", &n, &m)!=EOF)
	{
		init();
		ll ans = 0;
		for(int i = 1;i<=m;i++)
		{
			int u, v, w;
			scanf("%d%d%d", &u, &v, &w);
			add(u, v, w, i);
			add(v, u, w, i);
			val[i] = w;
		}
		scanf("%d", &st);
		spfa();
		for(int i = 1;i<=n;i++)
		{
			if(pre[i])
			ans+=val[pre[i]];
		}
		printf("%I64d\n", ans);
		for(int i = 1;i<=n;i++)
		{
			if(pre[i])
			printf("%d ", pre[i]);
		}
		printf("\n");
	}
	return 0;
}





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值