1.cheese
算法思路:dfs
我的代码:
#include<bits/stdc++.h>
using namespace std;
long long t,n,h,r;
struct point{
long long x,y,z;
}p[1005];
bool vis[1005],flag;
double dist(point a,point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));
}
void dfs(int cnt){
vis[cnt]=true;
if(p[cnt].z>=h-r){
flag=true;
return ;
}
for(int i=1;i<=n&&!flag;i++)
if(dist(p[cnt],p[i])<=r*2&&!vis[i])
dfs(i);
}
int main(){
scanf("%d",&t);
for(int i=1;i<=t;i++){
flag=false;
memset(vis,0,sizeof(vis));
scanf("%d%d%d",&n,&h,&r);
for(int i=1;i<=n;i++)
scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z);
for(int i=1;i<=n;i++)
if(p[i].z<=r&&!vis[i])
dfs(i);
if(flag)puts("Yes");
else puts("No");
}
}
估分:100
实际得分:100
反思:要开long long。
2.complexity
算法思路:要用树?
可能的思路:利用栈模拟。
标程:
#include<bits/stdc++.h>
#define ll long long
#define rint register int
using namespace std;
stack<int> zhan;
int main(){
int t;scanf("%d",&t);
while(t--){
int n;scanf("%d",&n);
int nowline=0,pos=0;
int Fcnt=0,Ecnt=0,cnt=0;
int hisans=0,myans=0;
int runflag=-1;
bool endflag=false;
string tmp;cin>>tmp;
string sublist="0";
for(rint i=0;i<tmp.length();++i)
if(tmp[i]>='0'&&tmp[i]<='9'){
hisans+=tmp[i]-'0';
hisans*=10;
}
hisans/=10;
if(tmp[2]=='1') hisans=0;
for(rint i=1;i<=n;++i){
string sub,opt,tmpsta,tmpend;
int sta=0,end=0;
cin>>opt;
if(opt=="F"){
++Fcnt;++pos;
zhan.push(pos);
cin>>sub>>tmpsta>>tmpend;
if(tmpend[0]=='n'&& (!(tmpsta[0]=='n'&&tmpend[0]=='n'))) ++cnt;
for(rint j=0;j<tmpsta.length();++j){
sta+=tmpsta[j]-'0';
sta*=10;
}
sta/=10;
if(tmpend[0]!='n'){//如果end是数字
for(rint i=0;i<tmpend.length();++i){
end+=tmpend[i]-'0';
end*=10;
}
end/=10;
if(sta>end)//如果循环不能执行
runflag=pos;
}
if(runflag==-1||pos<runflag) myans=max(myans,cnt);
sublist+=sub;
if(sublist.find(sub)!=sublist.length()-1){
printf("ERR\n");cnt=0;nowline=i;endflag=true;break;
}
sta=0;end=0;
}
else if(opt=="E"){
--cnt;++Ecnt;
if(zhan.empty()&&!endflag){
printf("ERR\n");cnt=0;nowline=i;endflag=true;break;
}
if(zhan.top()<=runflag){
pos=0;
runflag=-1;
}
if(!zhan.empty()) zhan.pop();
if(sublist.length()>0) sublist=sublist.substr(0,sublist.length()-1);
if(zhan.empty()) cnt=0;
}
}
if(endflag){
cnt=0;
while(!zhan.empty())
zhan.pop();
string cnm;
for(rint i=1;i<=n-nowline+1;++i) getline(cin,cnm);
continue;
}
if(Fcnt!=Ecnt){
if(!endflag) printf("ERR\n");
while(!zhan.empty()) zhan.pop();
cnt=0;
continue;
}
while(!zhan.empty()) zhan.pop();
if(!endflag){
if(myans==hisans) printf("Yes\n");
else printf("No\n");
}
myans=hisans=0;
}
return 0;
}
我的代码:
#include<bits/stdc++.h>
using namespace std;
int t,l,jie,fn,lf,cnt,maxx;
string m,start,end;
char type,name;
bool use[200],flag;
int decode(string m){
if(m[2]=='1')return 0;
else return (m[4]-48);
}
struct point{
int kind,fa;
vector<int> child;
}n[105];
void add(int a,int b){
n[a].child.push_back(b);
n[b].fa=a;
}
void dfs(int x,int j){
maxx=max(maxx,j);
if(n[x].kind==-1)
return ;
if(n[x].kind==1)
j++;
for(int i=0;i<n[x].child.size();i++)
dfs(n[x].child[i],j);
maxx=max(maxx,j);
return ;
}
int read(string x){
int len=x.size();
int sum=0,base=1;
for(int i=0;i<len;i++){
sum*=base;
sum+=x[i]-48;
base*=10;
}
return sum;
}
int main(){
scanf("%d",&t);
fn=0;
n[0].kind=0;
for(int i=1;i<=t;i++){
flag=true;
memset(use,false,sizeof(use));
for(int i=1;i<=104;i++){
n[i].kind=0;
n[i].fa=0;
n[i].child.clear();
}
lf=cnt=maxx=0;
scanf("%d",&l);
cin>>m;
jie=decode(m);
for(int i=1;i<=l;i++){
cin>>type;
if(type=='F'){
lf++;
cnt++;
add(fn,cnt);
fn=cnt;
cin>>name>>start>>end;
if(use[name])flag=false;
use[name]=true;
if(start=="n")n[cnt].kind=-1;
else if(end=="n")n[cnt].kind=1;
else{
int st=read(start);
int ed=read(end);
if(st>ed)n[cnt].kind=-1;
else n[cnt].kind=0;
}
}
else{
if(lf==0)flag=false;
lf--;
fn=n[fn].fa;
}
}
if(!flag||lf>0){
puts("ERR");
continue;
}
dfs(0,0);
if(maxx==jie)puts("Yes");
else puts("No");
}
}
估分:0
实际得分:27
反思:注意细节,不要盲目追求难答案。
3.classroom
算法思路:暂无
可能的思路:最短路+数学
标程:
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e3 + 5;
const double inf = 1e17 + 5;
int n, m, v, e, c[MAXN][2], mp[305][305];
double k[MAXN], dp[MAXN][MAXN][2], ans;
inline int read() {
char ch = getchar(); int u = 0, f = 1;
while (!isdigit(ch)) {if (ch == '-')f = -1; ch = getchar();}
while (isdigit(ch)) {u = u * 10 + ch - 48; ch = getchar();}return u * f;
}
int main(){
memset(mp, 63, sizeof(mp));
n = read(); m = read(); v = read(); e = read();
for (register int i = 1; i <= n; i++)c[i][0] = read();
for (register int i = 1; i <= n; i++)c[i][1] = read();
for (register int i = 1; i <= n; i++)scanf("%lf", &k[i]);
for (register int i = 1; i <= e; i++){
int x = read(), y = read(), w = read();
mp[x][y] = mp[y][x] = min(mp[x][y], w);
}
for (register int k = 1; k <= v; k++)
for (register int i = 1; i <= v; i++)
for (register int j = 1; j <= v; j++)
mp[i][j] = min(mp[i][j], mp[i][k] + mp[k][j]);
for (register int i = 1; i <= v; i++)mp[i][i] = mp[i][0] = mp[0][i] = 0;
for (register int i = 0; i <= n; i++)
for (register int j = 0; j <= m; j++)dp[i][j][0] = dp[i][j][1] = inf;
dp[1][0][0] = dp[1][1][1] = 0;
for (register int i = 2; i <= n; i++){
dp[i][0][0] = dp[i - 1][0][0] + mp[c[i - 1][0]][c[i][0]];
for (register int j = 1; j <= min(i, m); j++){
int C1 = c[i - 1][0], C2 = c[i - 1][1], C3 = c[i][0], C4 = c[i][1];
dp[i][j][0] = min(dp[i][j][0], min(dp[i - 1][j][0] + mp[C1][C3], dp[i - 1][j][1] + mp[C1][C3] * (1 - k[i - 1]) + mp[C2][C3] * k[i - 1]));
dp[i][j][1] = min(dp[i][j][1], min(dp[i - 1][j - 1][0] + mp[C1][C3] * (1 - k[i]) + mp[C1][C4] * k[i], dp[i - 1][j - 1][1] + mp[C2][C4] * k[i] * k[i - 1] + mp[C2][C3] * k[i - 1] * (1 - k[i]) + mp[C1][C4] * (1 - k[i - 1]) * k[i] + mp[C1][C3] * (1 - k[i - 1]) * (1 - k[i])));
}
}
ans = inf;
for (register int i = 0; i <= m; i++)ans = min(ans, min(dp[n][i][0], dp[n][i][1]));
printf("%.2lf", ans);
return 0;
}
估分:0
实际得分:0
反思:要观察每一道题,不要留空。
4.landlords
算法思路:暴力搜索
可能的思路:搜索+优化!!!
我的代码:
#include<bits/stdc++.h>
using namespace std;
int t,n,num,m,p[25][25],shen,minn=100000;
void copy(int step){
for(int i=0;i<=14;i++)p[step+1][i]=p[step][i];
}
void dfs(int step){
if(shen==0)return ;
for(int i=0;i<=14;i++){
if(p[step][i]>=4){
for(int j=0;j<=14;j++){
if(j==i)continue;
if(p[step][j]>0){
for(int k=0;k<=14;k++){
if(k==i||k==j)continue;
if(p[step][k]>0){
copy(step);
p[step+1][i]-=4;
p[step+1][j]-=1;
p[step+1][k]-=1;
shen-=6;
if(shen==0)minn=min(minn,step);
dfs(step+1);
shen+=6;
}
}
}
}
for(int j=0;j<=14;j++){
if(j==i)continue;
if(p[step][j]>1){
for(int k=0;k<=14;k++){
if(k==i||k==j)continue;
if(p[step][k]>1){
copy(step);
p[step+1][i]-=4;
p[step+1][j]-=2;
p[step+1][k]-=2;
shen-=8;
if(shen==0)minn=min(minn,step);
dfs(step+1);
shen+=8;
}
}
}
}
}
}
for(int i=0;i<=14;i++){
if(p[step][i]>=3)
for(int j=0;j<=14;j++){
if(j==i)continue;
if(p[step][j]>1){
copy(step);
p[step+1][i]-=3;
p[step+1][j]-=2;
shen-=5;
if(shen==0)minn=min(minn,step);
dfs(step+1);
shen+=5;
}
}
}
for(int i=3;i<=14;i++){
for(int j=2;i+j-1<=14;j++){
bool can=true;
for(int k=i;k<=i+j-1&&can;k++)
if(p[step][k]<3)can=false;
if(!can)continue;
copy(step);
for(int k=i;k<=i+j-1;k++)
p[step+1][k]-=3;
shen-=3*j;
if(shen==0)minn=min(minn,step);
dfs(step+1);
shen+=3*j;
}
}
for(int i=3;i<=14;i++){
for(int j=3;i+j-1<=14;j++){
bool can=true;
for(int k=i;k<=i+j-1&&can;k++)
if(p[step][k]<2)can=false;
if(!can)continue;
copy(step);
for(int k=i;k<=i+j-1;k++)
p[step+1][k]-=2;
shen-=2*j;
if(shen==0)minn=min(minn,step);
dfs(step+1);
shen+=2*j;
}
}
for(int i=0;i<=14;i++){
if(p[step][i]>=3)
for(int j=0;j<=14;j++){
if(j==i)continue;
if(p[step][j]>0){
copy(step);
p[step+1][i]-=3;
p[step+1][j]--;
shen-=4;
if(shen==0)minn=min(minn,step);
dfs(step+1);
shen+=4;
}
}
}
for(int i=3;i<=14;i++){
for(int j=5;i+j-1<=14;j++){
bool can=true;
for(int k=i;k<=i+j-1&&can;k++)
if(p[step][k]<1)can=false;
if(!can)continue;
copy(step);
for(int k=i;k<=i+j-1;k++)
p[step+1][k]-=1;
shen-=1*j;
if(shen==0)minn=min(minn,step);
dfs(step+1);
shen+=1*j;
}
}
for(int i=0;i<=14;i++){
for(int j=1;j<=p[step][i];j++){
copy(step);
p[step+1][i]-=1;
shen-=j;
if(shen==0)minn=min(minn,step);
dfs(step+1);
shen+=j;
}
}
}
int main(){
scanf("%d%d",&t,&n);
for(int q=1;q<=t;q++){
memset(p,0,sizeof(p));
for(int i=1;i<=n;i++){
scanf("%d%d",&num,&m);
if(num==1)num=14;
p[1][num]++;
}
shen=n;
minn=100000;
dfs(1);
printf("%d\n",minn);
}
}
标程:
#include<bits/stdc++.h>
using namespace std;
int T,n,ans,sum[25];
void dfs(int x)//x为出牌次数
{
if (x>=ans) return;
//顺子
int k=0;//单顺子
for (int i=3;i<=14;i++)//注意2和大小王不能考虑
{
if(sum[i]==0) k=0;//顺子断了
else
{
k++;//顺子长度增加
if(k>=5)//单顺子达到五张
{
for(int j=i;j>=i-k+1;j--) sum[j]--;//出牌
dfs(x+1);//继续搜
for(int j=i;j>=i-k+1;j--) sum[j]++;//回溯
}
}
}
k=0;//双顺子
for(int i=3;i<=14;i++)
{
if(sum[i]<=1) k=0;
else
{
k++;
if(k>=3)//双顺子达到三组
{
for(int j=i;j>=i-k+1;j--) sum[j]-=2;//出牌
dfs(x+1);
for(int j=i;j>=i-k+1;j--) sum[j]+=2;//回溯
}
}
}
k=0;//三顺子 //以下同理
for(int i=3;i<=14;i++)
{
if(sum[i]<=2) k=0;
else
{
k++;
if(k>=2)//三顺子达到两组
{
for(int j=i;j>=i-k+1;j--) sum[j]-=3;
dfs(x+1);
for(int j=i;j>=i-k+1;j--) sum[j]+=3;
}
}
}
//带牌
for(int i=2;i<=14;i++)//枚举有3张或4张的牌(这样才能带牌)
{
if(sum[i]<=3)
{
if(sum[i]<=2) continue;//三张以下(不含三张)不能带牌
sum[i]-=3;//出掉用来带别人的牌
for(int j=2;j<=15;j++)//带单张
{
if(sum[j]<=0||j==i) continue;//没有牌怎么带??
sum[j]--;//出掉被带的单张
dfs(x+1);
sum[j]++;//回溯
}
for(int j=2;j<=14;j++)//带一对
{
if(sum[j]<=1||j==i) continue;//没有一对怎么带?
sum[j]-=2;//出掉被带的一对
dfs(x+1);
sum[j]+=2;//回溯
}
sum[i]+=3;//回溯
}
else//大于3可以4带别的也可以3带别的
{
sum[i]-=3;//先用3张带别的
for(int j=2;j<=15;j++) //带单张 //以下原理同上
{
if(sum[j]<=0||j==i) continue;
sum[j]--;
dfs(x+1);
sum[j]++;
}
for(int j=2;j<=14;j++) //带一对
{
if(sum[j]<=1||j==i) continue;
sum[j]-=2;
dfs(x+1);
sum[j]+=2;
}
sum[i]+=3;
sum[i]-=4; //再用4张带别的
for(int j=2;j<=15;j++) //带2个单张
{
if(sum[j]<=0||j==i) continue;//自己不能带自己喽
sum[j]--;//出被带的第一张单张牌
for (int k=2;k<=15;k++)//找第二张单张
{
if(sum[k]<=0||j==k) continue;
sum[k]--;//出被带的第二张单张牌
dfs(x+1);
sum[k]++;//回溯
}
sum[j]++;//回溯
}
for(int j=2;j<=14;j++)//带2个对儿
{
if(sum[j]<=1||j==i) continue;
sum[j]-=2;//出被带的第一对牌
for(int k=2;k<=14;k++)
{
if(sum[k]<=1||j==k) continue;
sum[k]-=2;//出被带的第二对牌
dfs(x+1);
sum[k]+=2;//回溯
}
sum[j]+=2;//回溯
}
sum[i]+=4;//回溯
}
}
//把剩下的牌出完
for(int i=2;i<=15;i++) if(sum[i]) x++;
ans=min(ans,x);
}
int main()
{
scanf("%d%d",&T,&n);
while(T--)
{
ans=0x7fffffff;//搞大一点
int x,y;
memset(sum,0,sizeof sum);//多次询问,记得清零
for(int i=1;i<=n;i++)
{
scanf("%d%d",&x,&y);
if (x==0) sum[15]++;//把两张王存在一起(但是带牌的时候注意不要做对儿)
else if(x==1) sum[14]++;//由于A的牌值大所以往后放
else sum[x]++;//其他牌存在相应位置
}
dfs(0);//开始暴搜
printf("%d\n",ans);
}
}
估分:20
实际得分:30
反思:搜索优化不可少。