usaco 訓練總結4

2021-07-27 01:38:19 字數 4403 閱讀 9588

這裡都是些之前在codevs做的但在usaco4章節後沒有找到的(汗),覺得有必要記錄的題目

素數方陣

很刁鑽很刁鑽的暴搜

開始的思路:既然都是質數,那質數的最後一位一定是1,3,7或9,所以先預處理每一位都是1,3,7,9的,各個位和還滿足要求的質數,然後把他們分別列舉填到最後一行,最後一列,然後處理所有各個位和滿足要求的質數,並先填對角線,再橫著邊判斷邊填1,2,3,4行,天真的以為這樣就能過了。。。

然而還是我太天真。。。看了題解才發現人家優化很多

所以我再優化了自己的方法:

1,2,3步是原來的方法,然後列舉第4列的兩個數(4),並根據和算出第三位(6),然後列舉第4行的兩個數(5),並算出第三位(7),然後列舉第三列第乙個(8),然後依次算第三行第二個(9),第一行第二個(10),第一行第三個(11),第三列第二個(12),第一列第乙個(13)。

就此,此題就能過了,然而應該有更快速的做法,在下懶得想了。。。

#include#include#include#include#includeusing namespace std;

int he,zuo;

struct an

ans[10050];

int panyi(int x)

return 1;

}int paner (int x)

return 1;

}int pansan(int x)

return yu==he;

}int cnt,cnt2,num;

int map[5][5];

int nu10[5]=;

int ans1[1000],ans2[50000];

bool vis[100005];

void dfs(int x)

h1=map[4][0]*nu10[4]+map[3][1]*nu10[3]+map[2][2]*nu10[2]+map[1][3]*nu10[1]+map[0][4]*nu10[0];

if(!vis[h1])

return ;

num++;

for(int i=0;i<=4;i++)

return ;

} if(x==1)//(1)

}else if(x==2)//(2)

}else if(x==3)//(3) }

else if(x==4)//(4)(6)這裡和圖上所述的列舉位數以及順序有所偏差

} else if(x==5)//(5)(7)同上 }

else if(x==6)//(8)

}else if(x==7) }

int cmp(an a,an b)

an[105];

int s,b;

int main()

scanf("%d",&an[i].p);

} scanf("%d",&b);

for(int i=1;i<=b;i++)

scanf("%d%d%d",&l[i],&get[i],&p[i]);

for(int i=1;i<=s;i++)

for(int u=1;u<=ni[i];u++)

for(int lt=1;lt<=b;lt++)

if(an[i].k[u]==l[lt])

an[i].lo[lt]+=an[i].n[u];

dp[0][0][0][0][0]=0;

for(int i1=0;i1<=get[1];i1++)

dp[i1+1][i2][i3][i4][i5]=min(dp[i1+1][i2][i3][i4][i5],dp[i1][i2][i3][i4][i5]+p[1]);

dp[i1][i2+1][i3][i4][i5]=min(dp[i1][i2+1][i3][i4][i5],dp[i1][i2][i3][i4][i5]+p[2]);

dp[i1][i2][i3+1][i4][i5]=min(dp[i1][i2][i3+1][i4][i5],dp[i1][i2][i3][i4][i5]+p[3]);

dp[i1][i2][i3][i4+1][i5]=min(dp[i1][i2][i3][i4+1][i5],dp[i1][i2][i3][i4][i5]+p[4]);

dp[i1][i2][i3][i4][i5+1]=min(dp[i1][i2][i3][i4][i5+1],dp[i1][i2][i3][i4][i5]+p[5]);} }

}} }

cout布局

嗯,即便是裸題也要紀念一下使我首次接觸那個演算法的這個題啊

「有一種演算法,叫做差分約束」

#include#include#include#include#include#includeusing namespace std;

const int n=1050;

const int m=40050;

int head[n],to[m],v[m],next[m],cnt;

void add(int a,int b,int c)

int n,m1,m2;

bool vis[n],flag;

int c[n],dis[n];

queueq;

void spfa()

for(int i=head[now];i!=-1;i=next[i])

}} }

if(dis[n]==0x3f3f3f)

printf("-2\n");

else

if(flag==1)

printf("-1\n");

else

printf("%d\n",dis[n]);

}int main()

for(int i=1;i<=m2;i++)

spfa();

}

騎馬跨柵欄

嗯。。。。尤拉迴路。。。懶得詳講了

#include#include#include#include#includeusing namespace std;

int map[1000][1000];

int n,maxv,d[1500],sum=0,ans[1500];

void dfs(int x)

} ans[++sum]=x;

} int a,b;

int main()

int find=0;

for(int i=1;i<=maxv;i++) }

if(!find) }

dfs(find);

for(int i=sum;i>=1;i--)

cout排排站

這個題很吼啊。

首先,對於每個i,預處理1...i各個屬性出現過的個數,即各個屬性的字首和。

若一段符合要求,則有s[i][1]-s[j][1]=s[i][2]-s[j][2]=s[i][3]-s[j][3].....=s[i][m]-s[j][m];

這堆等式等價於:

s[j][2]-s[j][1]=s[i][2]-s[i][1],s[j][3]-s[j][1]=s[i][3]-s[i][1],s[j][4]-s[j][1]=s[i][4]-s[i][1].......s[j][m]-s[j][1]=s[i][m]-s[i][1]。

所以可以直接對每個i處理c[i][j]=s[i][j]-s[i][1],如果對於i,j,c[i][1]=c[j][1],c[i][2]=c[j][2]...c[i][m]=c[j][m]

那麼它們就為符合要求的序列。

查詢兩個相同的序列可以通過hush高效率地解決!

#include#include#include#include#includeusing namespace std;

const int mo=99997;

int n,m;

int gethush(int *a)

void add(int a,int b)

int now;

int dfs(int rt)

int ls=lin[rt].size()-1;

if(ls==-1)

return ans;

sort(lin[rt].begin(),lin[rt].end(),greater());

int i;

for(i=0;i<=ls;i++)

if(i<=ls)

ans=lin[rt][i]+1;

return ans;

// cout<

就此,這些便就是我在做usaco中碰到的覺得對自己有意義並且需要回顧的題目。

如果有誤,請神犇指出而勿噴

usaco訓練總結1

4.2.1 草地排水 裸的最大流 好像不滿足好題的標準。include include include include include include using namespace std struct bian vector tu 1050 bool vis 1050 void add int ...

usaco 訓練總結2

usaco 5.3.1 怎麼做呢?搜唄!void dfs int x,int cnt,int now for int i 1 i cnt i ans i b i return if x p return if vis now return 剪枝2 vis now cnt dfs x 1,cnt,no...

FZU ACM 聯合訓練 Day4總結

題意 給定乙個原始平面點集和乙個詢問平面點集,統計平面上有且僅有乙個頂點在詢問點集中的直角三角形的個數。兩個點集大小不超過 2000 題解 day 2原題來著?連我都會,極角排序,雙指標掃一遍統計答案,注意精度。感受 口胡的,打題還是要靠基礎紮實的公主。題意 給定乙個大小適當的正整數,問它的倒數在十...