下面是本次考核的补题:
序列树
在O. michestep王国,有一棵名叫Habaritran的树,树上有一个长度为 n 的序列 a,由于树的营养 不足,序列只由 0 和
1 构成,修理工Mitchell mitt觉得序列中每个连续的长度为 k 的子串中的0 与1
数量都相同,这棵树才看起来很nice。当然,修理工Mitchell mitt可以将序列中任何一个 0 修改成
1,也可以将任何一个1修改为0,请问修理工Mitchell mitt最少需要修改多少次,才能将这棵树变得nice。
输入
第一行包含两个正整数,分别为 n和k
第二行包含 n个数,每个数为 0 或者 1
输出
输出一行包含一个正整数,表示最少次数,如果序列怎么修改都不能让这棵树变nice,那么输出"-1"(不包含引号)
样例输
8 3
10100010
样例输出
-1
提示 数据范围 1 <= k <= n <= 10^6
对前k个字符串进行处理,不断变换起始点遍历,从而实现对每个位置需要变零和变一数量的掌控;
对获取到的前K个位置进行变化数量的排序,因为x,y的数量要相等,于是我们取能变化最少的x,与变化最少y 即是以x-y升序排列前取x后取y即可实现总数的最小化
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
const int maxn=103;
char t[maxn];
struct pt{
int x,y,z;
}p[maxn];
bool cmp(pt m,pt n)
{
return m.z <n.z ;
}
int n,k,m;
int main()
{
cin>>n>>k;
cin>>t;
if(k%2)
{
cout<<"-1"<<endl;
}
else
{
for(int i=0;i<k;i++)
{
for(int j=i;j<n;j+=k)
{
if(t[j]=='0')
p[i].x++;
else
p[i].y++;}
p[i].z=p[i].x-p[i].y;}
sort(p,p+k,cmp);
int ans;
for(int i=0;i<k/2;i++)ans+=p[i].x;
for(int i=k/2;i<k;i++) ans+=p[i].y;
cout<<ans<<endl;}
return 0;
}
广播系统
为了更加快速的传递学习任务,ACM集训队计划建设一个广播系统!按照规划,这个系统包含若干端点,这些端点由神奇的网络连接。 此网络有下述特点:
1.消息可以在任何一个端点产生,并且只能通过这个网络传递信息。每个端点接收消息后会将消息传送到与其相连的端点(单项传输,不会传输到那个消息发送过来的端点)
2.如果某个端点是产生消息的端点,那么消息将被传送到与其相连的每一个端点。
3.当消息在某个端点生成后,其余各个端点均能接收到消息
4.任意一个消息可以被快速的传给所有端点 现给你这个广播系统的连接方案,你能判断此系统是否符合以上要求并且传递给所有的端点?
输入
输入包含多组测试数据。每两组输入数据之间由空行分隔。
每组输入首先包含2个整数N和M,N(1<=N<=1000)表示端点个数,M(0<=M<=N*(N-1)/2)表示通信线路个数。
接下来M行每行输入2个整数A和B(1<=A,B<=N),表示端点A和B由神奇的网络相连。两个端点之间至多由一条网络直接相连,并且没有将某个端点与其自己相连的网络。
当N和M都为0时,输入结束。
输出
对于每组输入,如果所给的系统描述符合题目要求,则输出Yes,否则输出No。
样例输入
4 3
1 2
2 3
3 4
3 1
2 3
0 0
样例输出
Yes
No
这题是普通的并查集,但有一点不同的是要判断环状结构。
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=10005;
int fa[maxn],rk[maxn];
void inti(int n)
{
for(int i=1;i<=n;i++)
{
fa[i]=i;
rk[i]=0;}//初始化各节点
}
int find(int x)
{
if(fa[x]==x)
return x;
else
return fa[x]=find(fa[x]);
}
void unite(int x,int y)
{
x=find(x);
y=find(y);
if(x==y)
return ;
if(rk[x]<rk[y])
fa[x]=y;
else
{fa[x]=y;
if(rk[x]==rk[y])
rk[x]++;
}}
bool same(int x,int y)
{
return find(x)==find(y);
}//查询函数
int main()
{ int n,m,a,b;
while(cin>>n>>m)
{ int flag=0;int maxx=0;
if(n==0&&m==0)
break;
inti(n);
int ans=0;
for(int i=1;i<=m;i++)
{ cin>>a>>b;
unite(a,b);
}
for(int i=1;i<=n;i++)
maxx=max(maxx,fa[i]);
for(int i=1;i<=n;i++)
{
if(same(i,maxx))
ans++;}
if(ans==n&&m=n-1)//本题的核心步骤,不然只能 AC50%
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
迷宫
这道题是带拐角的bfs,当时卡在了第一步不算拐角没有初始化为-1而初始化为0
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1005;
char a[maxn][maxn];
int v[maxn][maxn];
struct pt{
int x;int y;
int corn;int d;
};
int dx[]={1,-1,0,0};int dy[]={0,0,1,-1};
int kk,n,m,p,q,x,y;
queue<pt>r;
void bfs()
{
while(!r.empty())
{if(r.front().x ==p&&r.front().y==q)
{
printf("yes\n");return ;
}
pt next;
for(int i=0;i<4;i++)
{
next.x = r.front().x+dx[i];
next.y = r.front().y +dy[i];
next.corn = r.front().corn;
next.d = i;
if( next.d!=r.front().d&&next.d!=-1) next.corn++;
if(next.x>0&&next.x <=m&&next.y>0&&next.y <=n&&!v[next.x ][next.y ]&&next.corn<=kk&&a[next.x ][next.y ]=='.')
{
v[next.x][next.y ]=1;
r.push(next);}
}
r.pop() ;
}
printf("no\n");
}
int main()
{ int t;
cin>>t;
while(t--)
{
cin>>m>>n;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
{
scanf(" %c",&a[i][j]) ;
}
scanf("%d%d%d%d%d",&kk,&y,&x,&q,&p);
pt fs;
fs.x=x;
fs.y=y;
fs.corn=-1;
fs.d=-1;
v[x][y]=1;
r.push(fs);
bfs();
memset(v,0,sizeof(v));}
return 0;
}
令人心动的秋季折扣
类似01背包,dp即可
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int M = 100 + 20;
int w[M];
int dp[M*100];//动态规划
int main()
{ int n;
while (cin>>n) {
int sum = 0;
for (int i = 0; i < n; ++i) {
scanf("%d", &w[i]);
sum += w[i];}
memset(dp, 0, sizeof(dp));
for (int i = 0; i < n; i++)
for (int j = sum/2; j >= w[i]; j--) {
if (dp[j] < dp[j-w[i]] + w[i]) {
dp[j] = dp[j-w[i]] + w[i];
}}
printf("%d\n", sum - dp[sum/2]*2);}
return 0;
}