1、彩色的砖块
思路:本题实际上是统计不同颜色砖块的数量,根据数量的不同进行输出就行。
源码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=100;
int main()
{
string s;
cin>>s;
stringstream ss(s);
int a[maxn];
int sum=0;
for (int i=0;i<maxn;i++) a[i]=0;
while(ss)
{
char tmp;
ss>>tmp;
a[tmp-'A']++;
}
for(int i=0;i<maxn;i++)
{
if(a[i]!=0)
sum++;
}
if(sum==1)
cout<<'1'<<endl;
if(sum==2)
cout<<'2'<<endl;
if(sum>=3)
cout<<'0'<<endl;
return 0;
}
2、等差数列
思路:本题目先排序,然后再根据等差数列的条件进行判断可以得到答案。
源码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=100;
int main()
{
int n,flag=1;
cin>>n;
int s[maxn];
for (int i=0;i<n;i++) cin>>s[i];
sort(s,s+n);
int d = s[1]-s[0];
for(int i=0;i<n-1;i++)
{
if(s[i]+d!=s[i+1])
{
flag=0;
break;
}
}
if(flag) cout<<"Possible"<<endl;
else cout<<"Impossible"<<endl;
return 0;
}
3、交错01串
思路:枚举起点,然后得到符合要求串的长度,选择最长的子串即可。
源码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=100;
int main()
{
int begin,end;
int lenth=0;
string s;
cin>>s;
for(int i=0;i<s.length();i++)
{
begin = i;
end = i;
while(!(s[end]-'0')==(s[end+1]-'0'))
end++;
if(end-begin+1>lenth)
{
lenth=end-begin+1;
}
}
cout<<lenth;
return 0;
}
4、操作序列
思路:本题可以将两步操作当成一步看,从结果中找出规律。实际上,因为第一步为加入到序列的末尾,然后进行逆序。可以得到这次加入的整数实际的位置在第一个。而上一次加入整数实际的位置被变化到最后一个。
源码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=200000+1000;
int main()
{
int a[maxn],b[maxn];
int an,begin=0;
cin>>an;
int end=an-1;
for(int i=0;i<an;i++) cin>>a[i];
for(int i=an-1;i>=0;i-=2)
{
b[begin++]=a[i];
if(end>begin-1)
b[end--]=a[i-1];
}
for(int i=0;i<an-1;i++) cout<<b[i]<<" ";
cout<<b[an-1]<<endl;
return 0;
}
5、独立的小易
思路:本题是一个线性规划问题,但是要注意 天数-f 可能出现负数,要进行区别的处理。另外寻找答案的时候,直接穷举要超时,可以通过二分查找。
源码:
#include<bits/stdc++.h>
using namespace std;
const long long maxn=2000000000;
int main()
{
long long x,f,d,p;
cin>>x>>f>>d>>p;
long long low=0,high=maxn;
long long mid=0;
while(low<=high)
{
mid=(low+high)/2;
if(mid-f>=0)
{
if(x*mid+(mid-f)*p<=d) low=mid+1;
else high=mid-1;
}
else
{
if(x*mid<=d) low=mid+1;
else high=mid-1;
}
}
mid=(low+high)/2;
cout<<mid<<endl;
return 0;
}
6、堆棋子思路:本题可以推导出最后各个棋子要移动的终点,X的范围就是在输入的X坐标中选择,Y的范围就是在输入的Y坐标中选择。具体证明推导可以百度本题得到。这样就可以枚举终点。然后进行计算每个棋子到达终点的步数、排序、就可以记录下所有终点,1个棋子到n个棋子的步数,然后再选择其中最少的步数输出。
源码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=50+10;
const int INF=0x3f3f3f3f;
int n,x[maxn],y[maxn],ans[maxn*maxn][maxn],anstmp[maxn],res=INF,res1[maxn];
int main()
{
//freopen("datain1.txt","r",stdin);
cin>>n;
for(int i=0;i<n;i++) cin>>x[i];
for(int i=0;i<n;i++) cin>>y[i];
for(int i=0;i<maxn*maxn;i++)
for(int j=0;j<maxn;j++)
ans[i][j]=0;
int len=0;
for(int i=0;i<n;i++)//枚举终点
{
for(int j=0;j<n;j++)
{
int sx=x[i],sy=y[j];
for(int k=0;k<n;k++)
anstmp[k]=abs(x[k]-sx)+abs(y[k]-sy);
sort(anstmp,anstmp+n);
for(int m=1;m<=n;m++)
{
for(int r=0;r<m;r++)
ans[len][m]=ans[len][m]+anstmp[r];
}
len++;
}
}
for(int m=1;m<=n;m++)
{
res=INF;
for(int r=0;r<len;r++)
res=min(res,ans[r][m]);
res1[m]=res;
}
for(int i=1;i<n;i++) cout<<res1[i]<<" ";
cout<<res1[n]<<endl;
return 0;
}
7、疯狂队列
思路:本题采用贪婪的思想,第一次先排最大身高和最小身高肯定是排在一起的。第二次是次小身高的和最大身高排在一起,次大的和最小身高排在一起。循环反复。但是要注意的是,当执行完还剩下最后一个数的时候,这个数需要和已经排好的队头和队尾比较,然后再排进去。
源码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1000+100;
int main()
{
int h[maxn],maxh[maxn];
for(int i=0;i<maxn;i++) maxh[i]=0;
int n,sum=0;
cin>>n;
for(int i=0;i<n;i++) cin>>h[i];
sort(h,h+n);
int pre=maxn/2,pos=maxn/2+1;
maxh[pre--]=h[n-1];
maxh[pos++]=h[0];
int cnt=0;
for(int i=1;i<=(n-1)/2;i++)
{
if(cnt%2==0)
{
if(n-1-i>i)
{
maxh[pre]=h[i];
pre--;
maxh[pos]=h[n-1-i];
pos++;
}
if(n-1-i==i)
{
if(abs(h[i]-maxh[pre+1])>abs(h[i]-maxh[pos-1]))
{maxh[pre]=h[i];pre++;}
else
{maxh[pos]=h[i];pos++;}
}
}
else
{
if(n-1-i>i)
{
maxh[pos]=h[i];
pos++;
maxh[pre]=h[n-1-i];
pre--;
}
if(n-1-i==i)
{
if(abs(h[i]-maxh[pre+1])>abs(h[i]-maxh[pos-1]))
{maxh[pre]=h[i];pre++;}
else
{maxh[pos]=h[i];pos++;}
}
}
cnt++;
}
pre=0;
while(!maxh[pre]) pre++;
for(int i=pre;i<pre+n-1;i++)
sum+=abs(maxh[i+1]-maxh[i]);
cout<<sum<<endl;
return 0;
}
8、小易喜欢的数列
思路:本题如果直接采用枚举的方法和普通的动态规划求解都只能通过40%的数据。
源码:
//参考链接:http://blog.youkuaiyun.com/shiwaigaoren12345/article/details/77248319
//本程序分层计算,在每一层通过排除不符合要求的数列,来计算得到本层符合要求数列的数量。
//其中状态dp[i][j]表示长度为i,以j结尾符合要求数量的数量
#include <iostream>
# define f(i,m,n) for(int i=m; i<=n; i++)
using namespace std;
const int mod=1000000007;
int dp[15][100010], last, now, n, k;
int main(){
cin>>n>>k;
last=0;
f(i, 1, k){
dp[1][i]=1;
last=(last+dp[1][i]%mod)%mod;
}
//计算d[i][j]的方式是通过排除
f(i, 2, n){//从长度为2开始计算
now=0; // now帮助last记录了在某个长度下,所有符合要求数列的数量
f(j, 1, k){ //从数1结尾开始枚举
int sum=0;
for(int t=2*j; t<=k; t=t+j)
sum=(sum+dp[i-1][t])%mod;
dp[i][j]=(last-sum+mod)%mod;
now=(now+dp[i][j])%mod;//now表示的为i+1层可以选的总数
}
last=now;
}
int ans=0;
f(i, 1, k) ans=(ans+dp[n][i])%mod;
cout<<ans<<endl;
return 0;
}