得了92.5分。辣鸡。懒惰的我不想去掉红字了,凑合着看吧。
题解:二分答案。
数据类型决定成败。30->85->100.
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #define N 200100 #define ll long long using namespace std; #ifdef unix #define LL "%lld" #else #define LL "%I64d" #endif ll n,m; ll k; ll ans; ll a[N],b[N]; void erfen(ll l,ll r) { if (l>r) return ; ll mid=(l+r)>>1; ll p(m),sum(0); for (ll i=1;i<=n;i++) { while (p>0&&a[i]*b[p]>mid) p--; sum+=p; } if (sum>=k) ans=mid,erfen(l,mid-1); else erfen(mid+1,r); } int main() { freopen("number.in","r",stdin); freopen("number.out","w",stdout); scanf(LL LL LL,&n,&m,&k); for (ll i=1;i<=n;i++) scanf(LL,&a[i]); for (ll i=1;i<=m;i++) scanf(LL,&b[i]); sort(a+1,a+n+1); sort(b+1,b+m+1); erfen(0,a[n]*b[m]); cout<<ans<<endl; fclose(stdin); fclose(stdout); return 0; }
题解:考试的时候想用搜索做,写min函数的时候定义成了bool型,,找了半天错误,咋就是返回1.然后还是可爱的小qg提醒,才知道要处理环。
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<ctime> #define N 10010 #define M 100010 #define ll long long using namespace std; int n,m,cnt(0); ll v[N]; int num[N][2]; ll minn; bool f[N]={0},vis[N]; struct node { int z; int x,y; }a[M]; int min(ll x,ll y) { if (x<y) return x; else return y; } ll dfs(int ki) { if (clock()>900) { printf("%d ",f[1]); fclose(stdin); fclose(stdout); return 0; } if (vis[ki]) return v[ki]; if (!f[ki]) return v[ki]; for (int i=num[ki][0];i<=num[ki][1];i++) { vis[ki]=1; v[ki]=min(v[ki],dfs(a[i].x)+dfs(a[i].y)); vis[ki]=0; } f[ki]=1; return v[ki]; } bool cmp(node c,node d) { if (c.z<d.z) return 1; else return 0; } int main() { freopen("dwarf.in","r",stdin); freopen("dwarf.out","w",stdout); scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%lld",&v[i]); for (int i=1;i<=m;i++) scanf("%d%d%d",&a[i].z,&a[i].x,&a[i].y); sort(a+1,a+m+1,cmp); for (int i=1,k;i<=m;i++) { k=a[i].z; if (!f[k]) f[k]=1,num[a[i-1].z][1]=i-1,num[k][0]=i; } num[a[m].z][1]=m; minn=dfs(1); cout<<minn<<endl; fclose(stdin); fclose(stdout); return 0; }
题解:看了正解之后,哦豁,好神奇,还能用spfa求。由于x,y能合成v,所以x—>v,距离是y;y->v,距离是x。然后跑最短路,这个最短距离就是得到物品i的最小代价。输出到1的最短距离即为解。
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #define N 100010 #define ll long long using namespace std; int n,m,Head(0),tail(0),num(0); int vi[N],dis[N],head[N]={0},team[N]; bool f[N]={0}; struct node { int v,t,pre; }e[N*2]; void add(int to,int from,int dis) { e[++num].v=to; e[num].t=dis; e[num].pre=head[from]; head[from]=num; } void spfa() { for (int i=1;i<=n;i++) { dis[i]=vi[i]; team[++tail]=i; f[i]=1; } while (Head<=tail) { int k=team[++Head]; f[k]=0; for (int i=head[k];i;i=e[i].pre) { int v=e[i].v; if (dis[v]>dis[k]+dis[e[i].t]) { dis[v]=dis[k]+dis[e[i].t]; if (f[v]==0) { f[v]=1; team[++tail]=v; } } } } } int main() { freopen("dwarf.in","r",stdin); freopen("dwarf.out","w",stdout); scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",&vi[i]); for (int i=1;i<=m;i++) { int v,x,y; scanf("%d%d%d",&v,&x,&y); add(v,x,y); add(v,y,x); } spfa(); printf("%d ",dis[1]); fclose(stdin); fclose(stdout); return 0; }
题解:神奇的多重背包。详情请见博客大犇lemon。
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #define N 100100 using namespace std; int n,V(0),num(0),ans(0); int a[N],b[N],c[N],d[N],w[N],v[N],f[N]; void xx(int wi,int vi,int ci)//二分制优化 { for (int i=1;i<=ci;i*=2) { ci-=i; v[++num]=vi*i; w[num]=wi*i; } if (ci) v[++num]=vi*ci,w[num]=wi*ci; } int main() { freopen("abcd.in","r",stdin); freopen("abcd.out","w",stdout); scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);//c[i]体积,d[i]价值,b[i]最大数量 b[i]-=a[i]; V-=a[i]*c[i]; ans+=a[i]*d[i];//由于价值实在基于-a[i]的前提下,因此最后要加上减去的价值。 } for (int i=1;i<=n;i++) xx(d[i],c[i],b[i]); for (int i=1;i<=num;i++) f[i]=-0x7fffffff/3; for (int i=1;i<=num;i++) for (int j=V;j>=v[i];j--) f[j]=max(f[j],f[j-v[i]]+w[i]); cout<<f[V]+ans<<endl; fclose(stdin); fclose(stdout); }