usaco2017febgold总结
Problem 1.为什么奶牛过马路1(visitfj)
题意
有一幅n*n的方格图,n <=100,每个点上有一个值。从(1,1)出发,走到(n,n),只能走上下左右。每走一步花费t,每走三步需要花费走完三步后到达格子的值。求最小花费的值。最短路径问题。
方法
用spfa解决,要拆点,dis[i][j]表示到达第i个点时走的总步数模3等于j时的最小花费值。
Problem 2. 为什么奶牛过马路II(nocross)
题意
上下有两个长度为n、位置对应的序列A、B,其中数的范围均为1~n。若abs(A[i]-B[j])<= 4,则A[i]与B[j]间可以连一条边。现要求在边与边不相交的情况下的最大的连边数量。n <= 10^4。
方法
用简单的最长公共连续子序列的DP方法来做。
CODE
#include<iostream>
#include<algorithm>
#include<cmath>
int n,a[1005],b[1005],f[1005][1005];
using namespace std;
int main()
{
cin>>n;
for (int i=1; i<=n; i++) cin>>a[i];
for (int i=1; i<=n; i++) cin>>b[i];
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
f[i][j]=max(f[i-1][j],f[i][j-1]);
if(abs(a[i]-b[j])<=4) f[i][j]=max(f[i][j],f[i-1][j-1]+1);
}
cout<<f[n][n]<<endl;
return 0;
}
题目大意:给定长度为2N的序列,1~N各处现过2次,i第一次出现位置记为ai,第二次记为bi,求满足ai<aj<bi<bj的对数。
思路:树状数组维护,从左到右扫一遍,第一次出现就在对应位置加1,第二次出现统计答案并把第一次出现的那个位置减1。
CODE
#include<iostream>
#include<algorithm>
using namespace std;
intans=0,a[1000005],p[10000005],c[1000005],n;
int lb(int k)
{
return k & (-k);
}
void modify(int k,int d)
{
while(k<=n*2)
{
c[k]+=d;
k+=lb(k);
}
}
int sum(int nn,int qq)
{
while(nn>0)
{
qq+=c[nn];
nn-=lb(nn);
}
returnqq;
}
int main()
{
cin>>n;
for(int i=1; i<=2*n; i++)
{
cin>>a[i];
if(p[a[i]]==0) {
p[a[i]]=i;modify(i,1);
}
else{
ans=ans+sum(i,0)-sum(p[a[i]],0);
modify(p[a[i]],-1);
}
}
cout<<ans;
return 0;
}