这道题卡了stl和cin,把输入的数换成字符串计算次数就行了。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int main(){
int n,k;
cin>>n>>k;
char ss[20];
int ans=0;
bool num[10];
while(n--){
memset(num,0,sizeof(num));
int count=0;
scanf("%s",ss);
for(int i=0;i<strlen(ss);i++){
int ind=ss[i]-'0';
num[ind]=1;
}
for(int i=0;i<10;i++){
if(num[i]==1)
count++;
}
if(count<k)
ans++;
}
cout<<ans<<endl;
return 0;
}
当初做用的算法是类似于求最长路的算法,先从一个点开始求距离最远的点,再从这个距离最远的点求另一个最远的点,再遍历每一个点,取到两个最远点的距离中的较大值,这个值最小的点就是保护罩中心。
但是爆零了,这个算法会出现意外情况,画个图就明白了。
正确算法:暴力求出到其他点的最大距离最小的那个点。
见代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include <bits/stdc++.h>
using namespace std;
struct location{
double x;
double y;
bool operator<(const location &t)const{
if(x!=t.x){
return x<t.x;
}
else{
return y<t.y;
}
}
}loc[1010];
double dist(location a,location b){
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>loc[i].x>>loc[i].y;
}
sort(loc,loc+n);
int fa,fb;
double dis=DBL_MAX;
int ansind=0;
for(int i=0;i<n;i++){
double tmp=0;
for(int j=0;j<n;j++){
if(i!=j){
tmp=max(tmp,dist(loc[i],loc[j]));
}
}
if(dis>tmp){
dis=tmp;
ansind=i;
}
}
printf("%.2lf %.2lf\n%.2lf",loc[ansind].x,loc[ansind].y,dis);
return 0;
}
这道题我竟然没有看出来是区间DP,想暴力求所有二叉搜索树的情况却败给。直到看了某大佬的博客才幡然醒悟,狂扇自己嘴巴。
算法:
首先求出所有的gcd值,存在gcdarr[][]二维数组中。gcdarr[i][j]表示第i个数和第j个数的gcd值。
开bool dp[][][]三维数组,dp[i][j][0]表示以ai为根,aj~ai-1为左子树的树是否成立,
dp[i][j][1]即ai为根,ai+1~aj为右子树的树是否成立。
如果成立置为1,不成立置为0。根据二叉搜索树的性质,如果i为根,j为左子树或者右子树中最小或者最大的那个树,j到i-1或者i+1到j都在这棵树里,我们所需要做的就是往左右扩展,如果往左扩展,也就是这棵树即将成为扩展到的数的右子树。
如果往右扩展,也就是这棵树即将成为扩展到的数的左子树。
状态转移方程
dp[j+1][i][0] |= gcdarr[j+1][k];
dp[i-1][j][1] |= gcdarr[i-1][k];
解释:
[i,j]成立,且[i,k],[k,j]都成立,也就是k是根,i 到k-1是左子树,k+1到j是右子树。
往右扩展时,j+1是根,原来的树成了j+1的左子树。
往左扩展,i-1是根,原来的树成了i-1的右子树。
好了,说了这么多,再结合代码,相信读者肯定能看明白。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=710;
int n,a[N];
bool gcdarr[N][N],dp[N][N][2];
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
memset(dp,0,sizeof(dp));
memset(gcdarr,0,sizeof(gcdarr));
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)
gcdarr[i][j]=0;
else
gcdarr[i][j]=(gcd(a[i],a[j])>1)?1:0;
}
}
for(int i=1;i<=n;i++)
dp[i][i][0]=dp[i][i][1]=1;
for(int j=1;j<=n;j++){
for(int i=j;i>=1;i--){
for(int k=i;k<=j;k++){
if(dp[k][i][0]&&dp[k][j][1]){
//j+1或i-1能不能插入树里
//状态转移方程
dp[j+1][i][0]|=gcdarr[j+1][k];
dp[i-1][j][1]|=gcdarr[i-1][k];
}
}
}
}
bool flag=false;
for(int i=1;i<=n;i++){
if(dp[i][1][0]&&dp[i][n][1]){
printf("Yes\n");
flag=true;
break;
}
}
if(flag==false)
printf("No\n");
}
return 0;
}