A - TT数鸭子
B - ZJM要抵御宇宙射线
C - 宇宙狗的危机
A - TT数鸭子
题目
思路
用stl会超时。。。最后用的vis标记统计数字种类数。
代码
#include <iostream>
#include <cstring>
using namespace std;
int n,k,ans=0,cnt,size_,temp;
string s;
bool vis[11];
int main() {
ios::sync_with_stdio(false);
cin>>n>>k;
for(int i=1;i<=n;i++) {
memset(vis,0,sizeof vis);
cin>>s;
cnt=0;
size_=s.size();
for(int j=0;j<size_;j++) {
temp=s[j]-'0';
if(vis[temp]==0) {
vis[temp]=1;
cnt++;
}
}
if(cnt<k) ans++;
}
cout<<ans<<endl;
return 0;
}
B- ZJM要抵御宇宙射线
题目
思路
看成最小圆覆盖,没看到题中说圆心是坐标点之一。。。遍历每两个点之间的距离,取所有距离中最大的距离,即为最大半径的最小值。
代码
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
int n;
double R;
struct point{
double x,y,r;
int maxp;
bool operator<(const point p_) {
if(x==p_.x) return y<p_.y;
else return x<p_.x;
}
}p[1100],ans;
double dis(point a,point b) {
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int main() {
cin>>n;
for(int i=1;i<=n;i++) cin>>p[i].x>>p[i].y;
sort(p+1,p+n+1);
for(int i=1;i<=n;i++) {
double tempr,maxr_=0;
int temp;
for(int j=1;j<=n;j++) {
tempr=dis(p[i],p[j]);
if(tempr>maxr_) {
maxr_=tempr;
temp=j;
}
}
p[i].r=maxr_;
p[i].maxp=temp;
}
int ans=1;
for(int i=1;i<=n-1;i++) {
if(p[ans].r>p[i].r) {
ans=i;
}
}
printf("%.2lf %.2lf\n",p[ans].x,p[ans].y);
printf("%.2lf\n",p[ans].r*p[ans].r);
return 0;
}
C- 宇宙狗的危机
题目
思路
采用动态规划的区间DP思想。用ans[i][j]表示a[i]-a[j]可以构成二叉树,则ans[1][n]为答案。用m[i][j]表示以a[i]为根的子树可以和以a[j]为根的子树合并,用Left[i][j]表示可以以a[j]为根,a[i]-a[j-1]作为左子树,用Right[i][j]表示可以以a[i]为根,a[i+1][j]作为右子树。经过区间长度,起始位置,根节点的枚举,最终得出答案。
代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int t,n,a[750];
bool ans[750][750],m[750][750],Left[750][750],Right[750][750];
int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }
int main(){
cin >> t;
for(int iii = 1; iii <= t; iii++){
memset(ans, 0, sizeof ans);
memset(m, 0, sizeof m);
memset(Left, 0, sizeof Left);
memset(Right, 0, sizeof Right);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
Left[i][i] = 1;
Right[i][i] = 1;
ans[i][i] = 1;
}
for (int i = 1; i <= n; i++){
for (int j = 1; j <= n; j++){
if (gcd(a[i], a[j]) > 1){
m[i][j] = 1;
}
}
}
for (int len = 0; len < n; len++){
for (int start = 1; start <= n-len; start++){
int end = start + len;
for (int root = start; root <= end; root++)
if (Left[start][root] && Right[root][end]){
ans[start][end] = 1;
if (m[root][end + 1]) Left[start][end + 1] = 1;
if (m[start - 1][root]) Right[start - 1][end] = 1;
}
}
}
if (ans[1][n]) cout << "Yes" << endl;
else cout << "No" << endl;
}
return 0;
}