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;
}