第一题:木桶研究
题意:给n块木板,选任意块组成一个水桶,其容量视为最短板的长度。现给出n块木板及其长度,求选单数块木板容量和与双数块木板容量和之差。
题解:对每块木板分析,其对答案贡献是与比其大者之组合数之差。化简可得所求实为最长板;sort一下即可。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<1)+(i<<3)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int i){
if(!i){putchar('0');return ;}
if(i<0){putchar('-');i=-i;}
while(i)buf[++buf[0]]=i%10,i/=10;
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
int n,w[1010];
signed main(){
n=read();
for(int i=1;i<=n;++i)
w[i]=read();
sort(w+1,w+n+1);
write(w[n]);
return 0;
}
第二题:木料开销
题意:给两个迭代函数求第n大值
题解:两个单调队列每次取最小值,注意去重
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<1)+(i<<3)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(long long i){
if(!i){putchar('0');return ;}
if(i<0){putchar('-');i=-i;}
while(i)buf[++buf[0]]=i%10,i/=10;
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
int z,n;
long long u1,v1,w1,u2,v2,w2,que1[10001000],que2[10001000];
int l1,l2,r1,r2;
signed main(){
z=read();n=read();
u1=read();v1=read();w1=read();
u2=read();v2=read();w2=read();
if(n==1){
write(z);
return 0;
}else{
l1=r1=l2=r2=1;
que1[l1]=u1*z/w1+v1;
que2[l2]=u2*z/w2+v2;
for(int i=2;i<n;++i){
if(que1[l1]<que2[l2]){
que1[++r1]=u1*que1[l1]/w1+v1;
que2[++r2]=u2*que1[l1]/w2+v2;
++l1;
}else{
que1[++r1]=u1*que2[l2]/w1+v1;
que2[++r2]=u2*que2[l2]/w2+v2;
++l2;
if(que1[l1]==que2[l2-1]) ++l1;
}
}
write(min(que1[l1],que2[l2]));
}
return 0;
}
第三题:木材运输
题意:在一有向图内有三火车,求火车到点权值相差在一定范围内的方案数
题解:注意数据范围(n<=50),且无环,每个点挨个bfs一遍用n^3数组存即可
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
#define mod 1000000007
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<1)+(i<<3)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(long long i){
if(!i){putchar('0');return ;}
if(i<0){putchar('-');i=-i;}
while(i)buf[++buf[0]]=i%10,i/=10;
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
int p[100],n,m,a,b,s1,s2,s3,k,f[51][51][51][3],first[100],nxt[3000],goal[3000];
struct trains{
int p1,p2,p3;
inline bool check(){
return (abs(p[p1]-p[p2])<=k)&&(abs(p[p1]-p[p3])<=k)&&(abs(p[p2]-p[p3])<=k);
}
};
int dfs(trains pos,int w){
if((w==0)&&!(pos.check())) return 0;
int x=pos.p1,y=pos.p2,z=pos.p3;
if(f[x][y][z][w]!=-1) return f[x][y][z][w];
if(w==0) f[x][y][z][w]=1; else f[x][y][z][w]=0;
if(w==0)
for(int p=first[x];p;p=nxt[p])
f[x][y][z][w]=(f[x][y][z][w]+dfs((trains) {goal[p],y,z},1))%mod;
if(w==1)
for(int p=first[y];p;p=nxt[p])
f[x][y][z][w]=(f[x][y][z][w]+dfs((trains) {x,goal[p],z},2))%mod;
if(w==2)
for(int p=first[z];p;p=nxt[p])
f[x][y][z][w]=(f[x][y][z][w]+dfs((trains) {x,y,goal[p]},0))%mod;
return f[x][y][z][w];
}
signed main(){
memset(f,-1,sizeof(f));
n=read();m=read();k=read();
for(int i=1;i<=n;++i)
p[i]=read();
for(int i=1;i<=m;++i){
a=read();b=read();
nxt[i]=first[a];
first[a]=i;
goal[i]=b;
}
s1=read();s2=read();s3=read();
write(dfs((trains){s1,s2,s3},0));
return 0;
}
第四题:木板排放
题意:n*m格图中放1*2之块,求方案数是否为1
题解:正解是两次二分图最大匹配,但是爆搜n+m遍也可以过...
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<1)+(i<<3)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(long long i){
if(!i){putchar('0');return ;}
if(i<0){putchar('-');i=-i;}
while(i)buf[++buf[0]]=i%10,i/=10;
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
const int xmove[4]={0,1,-1,0};
const int ymove[4]={1,0,0,-1};
char c[100][100];
int n,m,cnt,ii,jj;
signed main(){
n=read();m=read();
for(int i=1;i<=n;++i)
scanf("%s",c[i]+1);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
if(c[i][j]=='.') ++cnt;
if(cnt&1)puts("No");
else{
for(int t=1;t<=(n+m);++t){
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
if(c[i][j]=='.'){
cnt=0;
for(int k=0;k<4;++k){
ii=i+xmove[k];
jj=j+ymove[k];
if(c[ii][jj]=='.') ++cnt;
}
if(cnt==1){
c[i][j]='*';
for(int k=0;k<4;++k){
ii=i+xmove[k];
jj=j+ymove[k];
c[ii][jj]='*';
}
}
}
}
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
if(c[i][j]=='.'){
puts("No");
return 0;
}
puts("Yes");
}
return 0;
}