传送门

1.铺地毯

d1t1 模拟

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<ctime>
typedef long long LL;
using namespace std;
const int maxn=1e5+;
int n,xx,yy,x[maxn],y[maxn],c[maxn],k[maxn],ans;
int in(int x,int y,int c,int k) {
return x<=xx&&xx<=x+c&&y<=yy&&yy<=y+k;
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d%d%d%d",&x[i],&y[i],&c[i],&k[i]);
scanf("%d%d",&xx,&yy);
for(int i=;i<=n;i++)
if(in(x[i],y[i],c[i],k[i])) ans=i;
if(!ans) ans=-;
printf("%d\n",ans);
return ;
}

2.矩阵取数游戏

要命的高精。。太久没写高精写了大半晚上。。还写残了加个读优才卡过。。

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<ctime>
typedef long long LL;
const int maxn=+;
using namespace std;
int n,m,a[maxn][maxn],dp[maxn][maxn][],b[maxn],c[maxn],ans[maxn],power[maxn][],now[maxn]; int read() {
char ch=getchar(); int ret=;
while(ch<''||ch>'') ch=getchar();
for(;ch>=''&&ch<='';ch=getchar()) ret=ret*+ch-'';
return ret;
} void gcd(int x,int b[],int c[]) {
int y=;
for(int i=;i<=maxn;i++) c[i]=;
if(x==) return;
c[]=b[];
for(int i=;i<=b[];i++) {
c[i]=(b[i]*x+y)%;
y=(b[i]*x+y)/;
}
while(y) {
c[++c[]]=y%;
y/=;
}
} void gjg(int a[],int b[],int c[]) {
for(int i=;i<=maxn;i++) c[i]=;
int up=max(a[],b[]),x=;
c[]=up;
for(int i=;i<=up;i++) {
c[i]=(a[i]+b[i]+x)%;
x=(a[i]+b[i]+x)/;
}
while(x) {
c[++c[]]=x%;
x/=;
}
} int cmp(int bb[],int cc[],int d[]) {
int fl=;
if(bb[]<cc[])
fl=;
else if(bb[]==cc[]) {
for(int i=bb[];i>=;i--) {
if(bb[i]>cc[i]) break;
if(bb[i]<cc[i]) {fl=;break;}
}
}
if(fl) {
for(int i=;i<=cc[];i++)
d[i]=cc[i];
return ;
}
return ;
} void work(int id) {
now[]=;
for(int i=;i<=m;i++)
for(int j=;j+i<=m;j++) {
if(i!=) {
gcd(a[id][i],power[i+j],b);
gjg(dp[i-][j],b,c);
if( cmp(dp[i][j],c,b) ) {
for(int k=;k<=b[];k++)
dp[i][j][k]=b[k];
}
}
if(j!=) {
gcd(a[id][m-j+],power[i+j],b);
gjg(dp[i][j-],b,c);
if(cmp(dp[i][j],c,b)) {
for(int k=;k<=b[];k++)
dp[i][j][k]=b[k];
}
}
if(i+j==m) {
if( cmp(now,dp[i][j],c)) {
for(int k=;k<=c[];k++)
now[k]=c[k];
}
}
}
gjg(ans,now,c);
for(int i=;i<=c[];i++) ans[i]=c[i];
} int main()
{
n=read(); m=read();
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
a[i][j]=read();
power[][]=; power[][]=;
for(int i=;i<=;i++) {
gcd(,power[i-],c);
for(int j=;j<=c[];j++) power[i][j]=c[j];
}
for(int i=;i<=n;i++) {
memset(dp,,sizeof(dp));
work(i);
}
for(int i=ans[];i>=;i--)
printf("%d",ans[i]);
if(ans[]==) printf("0\n");
printf("\n");
return ;
}

3.传纸条

双线程dp

dp[k][i][j]表示走了k步一人走到第i行一人走到第j行的最优解。四种转移。

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<ctime>
typedef long long LL;
const int maxn=;
using namespace std;
int n,m,a[maxn][maxn],dp[maxn*][maxn][maxn];
int ok(int k,int i,int j) {
return i>=&&j>=&&(i!=j||(k==&&i==&&j==));
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
scanf("%d",&a[i][j]);
dp[][][]=;
for(int k=;k<=n+m-;k++)
for(int i=;i<=n&&i<=k+;i++)
for(int j=;j<=n&&j<=k+;j++)
if(i!=j||k==n+m-){
int now=a[i][k-i+]+a[j][k-j+];
if(ok(k-,i-,j-)) dp[k][i][j]=max(dp[k][i][j],dp[k-][i-][j-]+now);
if(ok(k-,i-,j)) dp[k][i][j]=max(dp[k][i][j],dp[k-][i-][j]+now);
if(ok(k-,i,j-)) dp[k][i][j]=max(dp[k][i][j],dp[k-][i][j-]+now);
if(ok(k-,i,j)) dp[k][i][j]=max(dp[k][i][j],dp[k-][i][j]+now);
}
printf("%d\n",dp[n+m-][n][n]);
return ;
}

4.车站

水题。

读错了三遍题看错了一遍样例,我大概是个傻子了。

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<ctime>
typedef long long LL;
const int maxn=;
int aa,n,m,x,a[maxn],b[maxn];
using namespace std;
int main()
{
scanf("%d%d%d%d",&aa,&n,&m,&x);
a[]=b[]=;
for(int i=;i<=n;i++) a[i]=a[i-]+a[i-],b[i]=b[i-]+b[i-];
if(n==) printf("%d\n",a);
else {
int bb=(m-(a[n-]+)*aa)/(b[n-]-);
printf("%d\n",aa*(a[x]+)+(b[x]-)*bb);
}
return ;
}

5.拼数

之前有学长讲过,前几天又刚好在sxy大佬博客里看到了。

string水过。

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<ctime>
typedef long long LL;
using namespace std;
const int maxn=;
int n;
string s[maxn];
bool cmp(const string&a,const string&b) {
return a+b>b+a;
}
int main()
{
cin>>n;
for(int i=;i<=n;i++) cin>>s[i];
sort(s+,s+n+,cmp);
for(int i=;i<=n;i++) cout<<s[i];
return ;
}

6.Cantor表

模拟。我不再是蛇形填数要写一个小时的我了。

7.旅行家的预算

一开始看了很久,想二分想dp什么的感觉很难受,然后瞎那啥贪了个心,结果A了?

感觉自己的贪心比较鬼畜。开一个单调队列,里面按从便宜到贵存油价和这个价的油还可以加多少。

每次从最便宜的油开始加,当然如果当前队列里最便宜的油都比现在贵了就一直pop。

从前往后加到可以开到下一个站。

然后若是容量大于该点到下一个点的耗油,把当前油加到队尾。质量为容量-此次耗油-队列中该点之前的所有点的容量和。

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<ctime>
#define INF 0x3f3f3f3f
typedef long long LL;
using namespace std;
double dp[][],len,c,v,w[],s[],ans,cs[],m[];
int n,fl,l=,r;
int main()
{
scanf("%lf%lf%lf%lf%d",&len,&c,&v,&w[],&n);
for(int i=;i<=n;i++) {
scanf("%lf%lf",&s[i],&w[i]);
}
s[n+]=len;
for(int i=;i<=n;i++) {
double now=(s[i+]-s[i])/v;
if(now>c) {fl=;break;}
if(l>r||w[i]<=cs[l]) {
l=;r=;
ans+=w[i]*now; }
else {
double tmp=;
while(w[i]>cs[l]&&tmp<now) {
if(now-tmp<m[l]) {
ans+=cs[l]*(now-tmp);
m[l]-=(now-tmp);
tmp=now;
}
else {
ans+=cs[l]*m[l];
tmp+=m[l];
l++;
}
}
if(tmp<now) {
ans+=(now-tmp)*w[i];
}
}
if(c-now>) {
cs[++r]=w[i];
m[r]=c-now;
for(int i=l;i<r;i++) m[r]-=m[i];
}
}
if(fl) cout<<"No Solution"<<endl;
else printf("%.2lf\n",ans);
return ;
}

8.进制转换

noip t1太难了QAQ。。我我我真的做不来。。。

如果模出来是负数就向前借一位。

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<ctime>
typedef long long LL;
using namespace std;
int n,base,power[],now,p[],f=-;
int main()
{
cin>>n>>base;
power[]=;
cout<<n<<"=";
while(n) {
p[++p[]]=n%base;
n/=base;
if(p[p[]]<) p[p[]]-=base,n++;
}
for(int i=p[];i>=;i--) {
if(p[i]<=) cout<<p[i];
else printf("%c",'A'+p[i]-);
}
cout<<"(base"<<base<<")"<<endl;
return ;
}

9.乘积最大

高精好难啊。

注意清空答案数组,记得清前导0;

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<ctime>
typedef long long LL;
using namespace std;
const int maxn=;
int n,kk,dp[][][maxn],now[maxn],c[maxn];
char a[];
int cal(int l,int r) {
for(int i=now[];i>=;i--) now[i]=;
for(int i=r;i>=l;i--) now[++now[]]=a[i]-'';
}
void cheng(int a[],int b[]) {
for(int i=c[];i>=;i--) c[i]=;
c[]=a[]+b[];
for(int i=;i<=a[];i++)
for(int j=;j<=b[];j++) {
int tp=c[i+j-]+a[i]*b[j];
c[i+j-]=tp%;
c[i+j]+=tp/;
}
while(c[c[]+]) {
++c[];
c[c[]+]=c[c[]]/;
c[c[]]%=;
}
while(c[]!=&&!c[c[]]) {c[]--;}
}
int cmp(int a[],int b[]) {
if(a[]>b[]) return ;
else if(a[]<b[]) return ;
for(int i=a[];i>=;i--) {
if(a[i]>b[i]) return ;
else if(a[i]<b[i]) return ;
}
return ;
}
int main()
{
cin>>n>>kk;
kk++;
scanf("%s",a+);
dp[][][]=dp[][][]=;
for(int i=;i<=n;i++) {
for(int j=;j<=i;j++) {
cal(j,i);
for(int k=;k<=kk;k++) if(dp[j-][k-][]>){
cheng(now,dp[j-][k-]);
if(cmp(c,dp[i][k])) {
for(int l=;l<=c[];l++)
dp[i][k][l]=c[l];
}
}
}
}
for(int i=dp[n][kk][];i>=;i--)
cout<<dp[n][kk][i];
return ;
}

10.单词接龙

题目没说清楚,是最小重叠,一开始算成最大重叠部分WA了一发。

我的做法,n^2枚举两个串,连在一起中间加个奇怪的符号,跑一遍kmp,最大重叠就直接取末尾的nxt,最小就一直往前跑到不能跑取nxt。

然后dfs。

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<ctime>
const int maxn=;
typedef long long LL;
using namespace std; char a[][],head[],s[]; int ans,n,f[][],nxt[],len[],vis[]; void make_nxt(int nn) {
for(int i=,k=;i<=nn;i++) {
while(k&&s[i]!=s[k]) k=nxt[k-];
if(s[i]==s[k]) k++;
nxt[i]=k;
}
} void dfs(int pos,int now) {
ans=max(ans,now);
for(int i=;i<=n;i++)
if(vis[i]<&&f[pos][i]>) {
vis[i]++;
dfs(i,now+len[i]-f[pos][i]);
vis[i]--;
}
} int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++) {
scanf("%s",a[i]);
len[i]=strlen(a[i]);
}
scanf("%s",head);
memset(f,-,sizeof(f));
for(int i=;i<=n;i++)
for(int j=;j<=n;j++) {
for(int k=;k<len[i];k++)
s[k]=a[i][k];
s[len[i]]='*';
for(int k=;k<len[j];k++)
s[len[i]+k+]=a[j][k];
make_nxt(len[i]+len[j]);
int tp=nxt[len[i]+len[j]];
while(nxt[tp-]) tp=nxt[tp-];
if(tp<len[i]) f[j][i]=tp;
}
for(int i=;i<=n;i++) {
if(a[i][]==head[]) {
vis[i]++;
dfs(i,len[i]);
vis[i]--;
}
}
cout<<ans<<endl;
return ;
}

11.税收与补贴问题

剧毒。

程序有bug,所有数据点下完了生平硬凑的AC。

反正在下是不想再看到这题了,太毒了。

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<ctime>
typedef long long LL;
const int maxn=1e6+;
using namespace std;
double v[maxn],m[maxn],vv,mm,ok,o,xy=1e9,dy=-1e9;
int k,n,ans;
int main()
{
scanf("%lf",&vv);
for(;;) {
n++;
scanf("%lf%lf",&v[n],&m[n]);
if(v[n]==-&&m[n]==-) {
break;
}
if(v[n]==vv) ok=,mm=m[n];
if(n!=) v[n]-=v[];
if(n!=&&(!k||v[n]>v[k])) k=n;
}
vv-=v[];
scanf("%lf",&o);
if(!ok) mm=m[k]-(vv-v[k])*o;
for(int i=;i<n;i++) {
double tmp=mm-m[i],tp=(m[i]*v[i]-mm*vv)/(tmp);
if(tmp>) dy=max(dy,tp);
else xy=min(xy,tp);
}
for(int i=m[k]/o;v[k]+i>=;i--) {
if(m[k]==&&i<) break;
v[n]=v[k]+i; m[n]=m[k]-i*o;
double tmp=mm-m[n];
if(tmp==) continue;
double tp=(m[n]*v[n]-mm*vv)/(tmp);
if(tmp>) dy=max(dy,tp);
else xy=min(xy,tp);
}
if(dy<&&xy>) ans=;
else if(dy>&&xy>) ans=dy+0.999999;
else ans=(xy-0.99999);
printf("%d\n",ans);
return ;
}
【】

- -

-

【】

- -

【】

- -

-

数据点 很水

12.一元三次方程求解

今天被noip题虐惨。。我太菜了。。

其实这题像我这样的zz不会可以水过

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<ctime>
#define eps 1e-6
typedef long long LL;
using namespace std;
double a,b,c,d,ans[];
int cnt;
double cal(double x){
return a*x*x*x+b*x*x+c*x+d;
}
int main()
{
scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
for(double i=-100.00;i<=100.00;i+=0.01)
if(fabs(cal(i))<eps) ans[++cnt]=i,i+=0.9;
for(int i=;i<=;i++)
printf("%.2lf ",ans[i]);
return ;
}

正解是类似之前讲的那啥苍蝇拍原理,每隔1判断一下区间内有解吗,有就二分。

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<ctime>
#define eps 1e-6
typedef long long LL;
using namespace std;
double a,b,c,d,ans[];
int cnt;
double cal(double x){
return a*x*x*x+b*x*x+c*x+d;
}
double ef(double ll,double rr) {
double l=ll,r=rr;
while(r-l>eps) {
double mid=(l+r)/;
if(cal(mid)*cal(l)<eps) r=mid;
else l=mid;
}
return l;
}
int main()
{
scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
for(int i=-;i<=;i++) {
if(cal(i)*cal(i+)<eps) {
ans[++cnt]=ef(i,i+);
i++;
}
}
for(int i=;i<=;i++)
printf("%.2lf ",ans[i]);
return ;
}

13.数的划分

可能今天脑子确实不好用。。当初刚学分苹果的问题就很头疼,今天写竟然连WA两发。。丢人丢到家了。。

给每人扔一个继续分或者把一个人丢了继续分。

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<ctime>
typedef long long LL;
using namespace std;
int n,k;
int fen(int n,int k) {
if(n==||k==) return ;
if(n>=k) return fen(n,k-)+fen(n-k,k);
else return fen(n,n);
}
int main()
{
cin>>n>>k;
if(n<k) cout<<<<endl;
else cout<<fen(n-k,k);
return ;
}

14.统计单词个数

暴力+dp;

枚举字符串的每个位置,算出它开头的单词最短到哪里。

然后暴力枚举转移;  时间复杂度比较高,可能数据比较水。

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<ctime>
typedef long long LL;
using namespace std;
int p,kk,now=,c,len[],ls[],dp[][];
char s[],dc[][];
int main()
{
scanf("%d%d",&p,&kk);
for(int i=;i<=p;i++) {scanf("%s",s+now); now+=;}
scanf("%d",&c);
for(int i=;i<=c;i++) {
scanf("%s",dc[i]);
len[i]=strlen(dc[i]);
}
for(int i=;i<=p*;i++) {
int r=;
for(int j=;j<=c;j++) {
for(int k=;k<len[j];k++) {
if(s[i+k]!=dc[j][k]) break;
if(k==len[j]-) r=min(r,i+k);
}
}
if(r!=) ls[i]=r;
}
memset(dp,,sizeof(dp));
dp[][]=;
for(int i=;i<=p*;i++) {
for(int j=;j<=i;j++) {
int now=;
for(int k=j;k<=i;k++)
if(ls[k]&&ls[k]<=i) now++;
for(int k=;k<=kk;k++) {
dp[i][k]=max(dp[i][k],dp[j-][k-]+now);
}
}
}
printf("%d\n",dp[p*][kk]);
return ;
}

15.Car的旅行路线

题很简单,一个最短路。只是写起来比较麻烦。

知道三点求矩形第四点,用向量叉乘判断垂直,中点坐标公式求出第四点。

建边暴力跑spfa;

一开始把一个double存成int de了一个小时bug.....

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<ctime>
typedef long long LL;
using namespace std;
const int maxn=; int T,n,tot,s,t,fir[maxn],nxt[maxn*maxn],to[maxn*maxn],id[maxn],ecnt;
double ans,cost,x[maxn],y[maxn],w[maxn],val[maxn*maxn]; void add(int u,int v,double w) {
nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; val[ecnt]=w;
nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u; val[ecnt]=w;
} int pre(int a,int b,int c) {
return (x[b]-x[a])*(x[c]-x[a])+(y[b]-y[a])*(y[c]-y[a])==;
} void check(int a,int b,int c) {
if(pre(a,b,c)) {
double xx=(x[b]+x[c])/,yy=(y[b]+y[c])/;
xx=xx*-x[a], yy=yy*-y[a];
x[tot]=xx; y[tot]=yy;
}
else if(pre(b,a,c)) {
double xx=(x[a]+x[c])/,yy=(y[a]+y[c])/;
xx=xx*-x[b], yy=yy*-y[b];
x[tot]=xx; y[tot]=yy;
}
else {
double xx=(x[b]+x[a])/,yy=(y[b]+y[a])/;
xx=xx*-x[c], yy=yy*-y[c];
x[tot]=xx; y[tot]=yy;
}
} double dis(int i,int j) {
return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
} queue<int>que;
int vis[maxn];
double di[maxn];
void spfa() {
ans=1e9;
while(!que.empty()){
int x=que.front();
if(id[x]==t) ans=min(ans,di[x]);
que.pop(); vis[x]=;
for(int i=fir[x];i;i=nxt[i]) {
if(di[to[i]]>di[x]+val[i]) {
di[to[i]]=di[x]+val[i];
if(!vis[to[i]]) {
vis[to[i]]=;
que.push(to[i]);
}
}
}
}
} int main()
{
scanf("%d",&T);
while(T--) {
memset(fir,,sizeof(fir));
memset(di,,sizeof(di));
memset(vis,,sizeof(vis));
ecnt=;
scanf("%d%lf%d%d",&n,&cost,&s,&t);
for(int i=;i<=n;i++) {
for(int j=;j<=;j++) {tot++; scanf("%lf%lf",&x[tot],&y[tot]);}
tot++; int a=tot-,b=tot-,c=tot-;
check(a,b,c);
id[a]=id[b]=id[c]=id[tot]=i;
scanf("%lf",&w[i]);
if(i==s) {
di[a]=di[b]=di[c]=di[tot]=;
que.push(a); que.push(b); que.push(c); que.push(tot);
vis[a]=vis[b]=vis[c]=vis[tot]=;
}
}
for(int i=;i<=tot;i++)
for(int j=;j<=tot;j++) if(i!=j) {
if(j==) {
int debug=;
}
double d=dis(i,j);
if(id[i]==id[j]) add(i,j,d*w[id[i]]);
else add(i,j,d*cost);
}
spfa();
printf("%.1lf\n",ans);
}
return ;
}

16.均分纸牌

直接模拟。应该叫贪心吧?

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<ctime>
typedef long long LL;
using namespace std;
int n,a[],ave,tot;
int main()
{
cin>>n;
for(int i=;i<=n;i++) { cin>>a[i]; ave+=a[i];}
ave/=n;
for(int i=;i<=n;i++) {
if(a[i]!=ave) {
tot++;
a[i+]-=(ave-a[i]);
}
}
cout<<tot;
return ;
}

17.

18.自由落体

模拟。理论AC。

19.矩形覆盖

搜索,和之前考试的兔子题差不多。理论AC。

20.神经网络

拓扑排序裸题。理论AC。

21.加分二叉树

之前在vijos上交过。记忆化搜索。

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn=;
int a[maxn],n,dp[maxn][maxn],lc[maxn],rc[maxn];
int dfs(int l,int r) {
if(l==r) dp[l][r]=a[l];
if(dp[l][r]) return dp[l][r];
for(int i=l;i<=r;i++) {
int ll=(i==l?:dfs(l,i-)),rr=(i==n?:dfs(i+,r));
dp[l][r]=max(dp[l][r],ll*rr+a[i]);
}
return dp[l][r];
}
void print(int l,int r) {
if(l==r) {printf("%d ",l); return;}
for(int i=l;i<=r;i++) {
int ll=(i==l?:dfs(l,i-)),rr=(i==n?:dfs(i+,r));
if(dp[l][r]==ll*rr+a[i]){
print(i,i);
if(i!=l) print(l,i-);
if(i!=r) print(i+,r);
break;
}
}
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&a[i]);
printf("%d\n",dfs(,n));
print(,n);
return ;
}

22.传染病控制

第一眼贪心,然而洛谷题解给出了这样的图。(侵删)

然后考虑dp,预处理出每条边切掉的贡献,跑背包?发现前面的选择对后面有影响,不可做。只有爆搜+剪枝了。

后面去看别人的搜索发现好像大多是直接搜索,把前面选过的标记一下不再选了

自己用队列维护了一下,感觉跑得会快一点。

当然要加个估价最优化剪枝。

//Twenty
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<ctime>
#include<queue>
const int maxn=;
typedef unsigned long long LL;
using namespace std;
int n,p; int ecnt,fir[maxn],nxt[maxn*],to[maxn*],sz[maxn];
void add(int u,int v) {
nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u;
} int fa[maxn],R[maxn];
void Dfs(int x,int f) {
fa[x]=f; R[x]=R[f]+; sz[x]=;
for(int i=fir[x];i;i=nxt[i]) if(to[i]!=f) {
Dfs(to[i],x);
sz[x]+=sz[to[i]];
}
} int ans,que[maxn],ql=,qr;
void dfs(int now) {
int rn=R[que[ql]],gj=,gs=;
while(ql<=qr) {
int x=que[ql];
if(R[x]!=rn) break;
for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa[x]){
que[++qr]=to[i];
gj+=sz[to[i]]; gs++;
}
ql++;
}
if(ql>qr) ans=max(ans,now);
else if(ql==qr) ans=max(ans,now+sz[que[ql]]);
else {
gj-=sz[que[qr]];
int tp=que[qr]; qr--;
dfs(now+sz[tp]);
for(int i=qr;i>=ql;i--) {
gj+=sz[tp]; gj-=sz[que[i]];
swap(tp,que[i]);
if(gj-gs++now+sz[tp]<=ans) continue;
dfs(now+sz[tp]);
}
}
while(R[que[qr]]!=rn) qr--;
while(R[que[ql-]]==rn) ql--;
} int main()
{
scanf("%d%d",&n,&p);
for(int i=;i<=p;i++) {
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
}
Dfs(,);
que[++qr]=;
dfs();
printf("%d\n",sz[]-ans);
return ;
}

23.谁拿了最多奖学金

简单模拟。

贴个以前在openjudge上交的鬼畜代码。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <iomanip>
#include <cstring>
using namespace std;
int main()
{
int n,jin=;
string name,na;
int qi,ban,lun,max=,s=;
char xu,xi;
cin>>n;
for(int i=;i<=n;i++) {
cin>>name>>qi>>ban>>xu>>xi>>lun;
if(qi>&&lun>=)jin+=;
if(qi>&&ban>)jin+=;
if(qi>)jin+=;
if(qi>&&xi=='Y')jin+=;
if(ban>&&xu=='Y')jin+=;
s+=jin;
if(jin>max){max=jin;na=name;}
jin=;
}
cout<<na<<"\n"<<max<<"\n"<<s;
return ;
}

24.过河

dp。路径压缩。

可以证明可以直接mod t*(t-1) ,可惜我不会。

退求其次可以mod2520 (gcd(1……10));

//Twenty
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<ctime>
#include<queue>
typedef long long LL;
using namespace std;
const int mod=;
int l,s,t,m,a[],is[*],dp[*],ans=1e9;
int main()
{
scanf("%d%d%d%d",&l,&s,&t,&m);
for(int i=;i<=m;i++) scanf("%d",&a[i]);
sort(a+,a+m+);
for(int i=;i<=m;i++) {
a[i]=a[i-]+(a[i]-a[i-])%mod;
is[a[i]]=;
}
l=a[m]+(l-a[m])%mod;
memset(dp,/,sizeof(dp));
dp[]=;
for(int i=;i<=l+t;i++) {
for(int j=s;j<=t;j++)
dp[i+j]=min(dp[i+j],dp[i]+is[i+j]);
}
for(int i=l;i<=l+t;i++) ans=min(ans,dp[i]);
printf("%d\n",ans);
return ;
}

25.能量项链

//Twenty
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<ctime>
#include<queue>
typedef long long LL;
using namespace std;
const int maxn=;
int n,l[maxn],r[maxn],dp[maxn][maxn],ans;
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&l[i]);
for(int i=;i<=n;i++) l[n+i]=l[i];
for(int i=;i<=*n;i++) r[i]=l[i+]; r[*n]=l[];
for(int i=;i<=n;i++) {
for(int j=;j+i-<=*n;j++) {
for(int k=j;k<j+i-;k++) {
dp[j][j+i-]=max(dp[j][j+i-],dp[j][k]+dp[k+][j+i-]+l[j]*r[k]*r[j+i-]);
}
}
}
for(int i=;i<=n;i++) ans=max(ans,dp[i][i+n-]);
printf("%d\n",ans);
return ;
}

26.篝火晚会

怀疑自己是个zz....一开始建环都建错了......然后没有取反一直WA......

贪心,先把目标序列找出来,然后从某个人开始往后数一圈和目标序列不同的人数的最小值就是最小的交换代价。

当然不可能n^2往后数,考虑根据目标序列的每一位推出这一位在这里的序列开头是哪位,cnt++,找出cnt最大的即可。

然后坑点,题目要求的一圈人其实顺时针和逆时针是一样的,比如  4 3 2 1 == 2 3 4 1;

所以序列取反再跑一遍。

//Twenty
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
const int maxn=;
using namespace std;
int fl,n,a[maxn],b[maxn],l[maxn],r[maxn],c[maxn],mx,st,tid[maxn],ok[maxn],in[maxn],vis[maxn],ans;
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
scanf("%d%d",&l[i],&r[i]);
int pr=;
for(int x=;;) {
b[++b[]]=x;
vis[x]++;
if(vis[x]==) {
if(x==) {
b[b[]--]=;
break;
}
else {
printf("-1\n");
return ;
}
}
tid[x]=b[];
int tp=pr; pr=x;
if(l[x]==tp) x=r[x];
else x=l[x];
}
for(int i=;i<=n;i++) {
if(!vis[i]) {
printf("-1\n");
return ;
}
}
for(int i=;i<=n;i++) {
int x=b[i]-i+;
if(x<=) x+=n;
c[x]++;
if(c[x]>mx) mx=c[x],st=x;
}
memset(c,,sizeof(c));
int up=n/;
for(int i=;i<=up;i++) swap(b[i],b[n-i+]);
for(int i=;i<=n;i++) {
int x=b[i]-i+;
if(x<=) x+=n;
c[x]++;
if(c[x]>mx) mx=c[x],st=x;
}
printf("%d\n",n-mx);
return ;
}

27.等价表达式

带入几个值计算答案。听说有左右括号不匹配的情况极其坑。

每次找优先度最低的符号,计算左右然后合并。

太恶心了不想写了,放个垃圾的三分之一成品

//Twenty
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
using namespace std;
typedef long long LL;
const int mod=1e9+;
int n,as,fl;
LL f[][][],p[];
char ss[]; int ksm(int a,int b) {
LL res=,base=a;
while(b) {
if(b&) (res*=base)%=mod;
(base*=base)%=mod;
b>>=;
}
return res;
} void cal(int l,int r) {
int ll=l,rr=r,tt=; if(ss[l]=='('&&ss[r]==')') ll++,rr--;
if(ll==rr) {for(int i=;i<=;i++) f[l][r][i]=i; return;}
int mx=,k=;
for(int i=l;i<=r;i++) {
if(ss[i]=='(') tt++;
else if(ss[i]==')') tt--;
else if(tt==){
int x=(ss[i]=='+'||ss[i]=='-')?:((ss[i]=='*')?:);
if(x<mx) {k=i,mx=x;}
}
}
cal(l,k-); cal(k+,r);
for(int i=;i<=;i++) {
if(ss[k]=='+') f[l][r][i]=(f[l][k-][i]+f[k+][r][i])%mod;
if(ss[k]=='-') f[l][r][i]=(f[l][k-][i]-f[k+][r][i]+mod)%mod;
if(ss[k]=='*') f[l][r][i]=(f[l][k-][i]*f[k+][r][i])%mod;
if(ss[k]=='^') f[l][r][i]=ksm(f[l][k-][i],f[k+][r][i]);
}
} int main()
{
scanf("%s",ss);
int up=strlen(ss)-;
cal(,up);
for(int i=;i<=;i++) p[i]=f[][up][i];
scanf("%d",&n);
for(int i=;i<=n;i++) {
memset(f,,sizeof(f));
scanf("%s",ss);
up=strlen(ss)-;
int tt=;
for(int j=;j<=up;j++) { if(ss[j]=='(') tt++; else if(ss[j]==')') tt--;}
if(tt!=) continue;
cal(,up);
for(int j=;j<=;j++) {
if(f[][up][j]!=p[j]) break;
if(j==) as++;
}
}
printf("%d\n",as);
return ;
}

28.作业调度方案

模拟题。因为时间很小,枚举目前加工的东西,从这个工件上一次加工完成的时间开始枚举,一个个试能不能插进去。

没写,放一个别人的代码

//Twenty
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
using namespace std;
int n,m,seq[*],num[][],t[][],cnt[],last[];
bool used[][];
bool check(int start,int len,int mac)
{
bool f=true;
for(int i=start;i<start+len;i++) if(used[mac][i]) f=false;
return f;
}
int main()
{
cin >> m >> n;
for(int i=;i<=n*m;i++) cin >> seq[i];
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
cin >> num[i][j];
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
cin >> t[i][j];
for(int i=;i<=n*m;i++)
{
cnt[seq[i]]++;
int x=seq[i],y=cnt[seq[i]],z=num[x][y];
for(int j=last[x];;j++)
{
if(check(j,t[x][y],z))
{
for(int k=j;k<j+t[x][y];k++) used[z][k]=true;
last[x]=j+t[x][y];
break;
}
}
}
int res=;
for(int i=;i<=n;i++)
{
res=max(res,last[i]);
}
cout << res;
return ;
}

29.2^k进制数

第一眼数位dp,发现其实可以直接用组合数求解。

因为左边严格大于右边,长度为i的2^k进制数的合法解的个数为 C(2^k-1,i);

这样算出没有到最高位的数,到最高位的数的个数枚举最高位可以达到的数i,ans+=C[2^k-1-i][up-1];

然后要写高精,很恶心。

一开始读错题以为左边比右边大,WA了一发,然后高精数组没清干净要判断组合数后一维小于等于前一维不然会出现奇怪的错误。

//Twenty
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
using namespace std;
typedef long long LL;
const int nn=<<;
int k,w,C[nn][nn][],c[],ans[]; void gj(int a[],int b[],int c[]) {
c[]=max(a[],b[]);
int x=;
for(int i=;i<=c[];i++) {
c[i]=(a[i]+b[i]+x)%;
x=(a[i]+b[i]+x)/;
}
while(x) {
c[++c[]]=x%;
x/=;
}
} void pre() {
for(int i=;i<nn;i++) C[i][][]=C[i][][]=;
for(int i=;i<nn;i++)
for(int j=;j<=i;j++) {
gj(C[i-][j],C[i-][j-],C[i][j]);
}
} void init() {
scanf("%d%d",&k,&w);
} void work() {
int up=(<<k)-,upp=(w-)/k+;
for(int i=;i<upp&&i<=up;i++) {
gj(ans,C[up][i],c);
for(int i=c[];i>=;i--) ans[i]=c[i];
}
int u;
if(k==) u=;
else {
int ww=w%k;
if(!ww) ww=k;
u=(<<ww)-;
}
for(int i=;i<=u;i++) {
if(i) {
memset(c,,sizeof(c));
if(upp-<=up-i) {
gj(ans,C[up-i][upp-],c);
for(int i=c[];i>=;i--) ans[i]=c[i];}
}
}
for(int i=ans[];i>=;i--)
printf("%d",ans[i]);
printf("\n");
} int main()
{
pre();
init();
work();
return ;
}
两组数据

30.虫食算

一直听说是道搜索神题,今天看了看看到其实正解是高斯消元?别人代码贼长就懒得看了。

搜索可做。爆搜可以过80,每次搜上面两个,下面一个直接算出来,要是某个地方不合法了就跳出,到了最后余数要不为0。

然后改变一下搜索顺序,比如玄学地加个rand_shuffle()(我也不知道为什么我这么喜欢这个函数)或者从后往前搜就可以过90,再卡一卡常在codevs上开2s的就A了。

正确的剪枝方法:每枚举一个数的时候预先判断一下前面不合法的情况,枚举前面每一位要是三位都已经确定了且不管进不进位三位都不匹配就不搜下去了。

于是就跑得贼快。

//Twenty
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
typedef long long LL;
using namespace std;
int n,k[],ok[],yh[],xx;
char a[][]; int check(int x) {
for(int i=x;i>=;i--) {
int aa=k[a[][i]],bb=k[a[][i]],cc=k[a[][i]];
if(aa!=-&&bb!=-&&cc!=-) {
if(((aa+bb)%n!=cc)&&((aa+bb+)%n!=cc)) return ;
}
}
return ;
} int dfs(int l,int x) {
int pr=xx;
if(l==-) {
if(!xx) return ;
else return ;
}
if(k[a[x][l]]!=-) {
if(x==) {
if((k[a[][l]]+k[a[][l]]+xx)%n==k[a[][l]]) {
xx=(k[a[][l]]+k[a[][l]]+xx)/n;
if(dfs(l-,)) return ;
else {xx=pr; return ;}
}
else return ;
}
else {
if(dfs(l,x+)) return ;
return ;
}
}
else {
if(x==) {
int tp=(k[a[][l]]+k[a[][l]]+xx)%n;
if(ok[tp]&&ok[tp]!=a[l][]) return ;
if(ok[tp]) {
xx=(k[a[][l]]+k[a[][l]]+xx)/n;
if(dfs(l-,)) return ;
else {xx=pr; return ;}
}
else {
k[a[x][l]]=tp; ok[tp]=a[x][l];
xx=(k[a[][l]]+k[a[][l]]+xx)/n;
if(dfs(l-,)) return ;
k[a[x][l]]=-; ok[tp]=; xx=pr;
return ;
}
}
else {
for(register int i=;i<n;i++) if(!ok[yh[i]]){
k[a[x][l]]=yh[i]; ok[yh[i]]=a[x][l];
if(check(l)) {if(dfs(l,x+)) return ;}
k[a[x][l]]=-; ok[yh[i]]=; xx=pr;
}
}
}
return ;
} void read() {
scanf("%d",&n);
char ch=getchar();
for(int i=;i<=;i++) {
int sz=-;
while(ch<'A'||ch>'Z') ch=getchar();
for(;ch>='A'&&ch<='Z';ch=getchar()) a[i][++sz]=ch;
}
} int main()
{
read();
memset(k,-,sizeof(k));
for(register int i=;i<n;i++) yh[i]=n-i-;
dfs(n-,);
for(register int i=;i<n;i++) {
printf("%d ",k['A'+i]);
}
printf("\n");
return ;
}

31.斗地主/斗地主增强版

搜索+贪心神题。

不想说话。一个点一个点改。

再也不写这种神题了,再写剁手。

//Twenty
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
typedef long long LL;
using namespace std;
int T,n,a[],tp,ans;
char s[]; void work(int now) {
int b[],p[];
for(int i=;i<=;i++) p[i]=;
for(int i=;i<=;i++) {
b[i]=a[i];
p[a[i]]++;
}
if(a[]&&a[]) p[]++;
else if(a[]||a[]) p[]++;
while(p[]) {
if(p[]&&(p[]+p[]<=p[])) p[]--;
if(p[]>=) p[]-=;
else if(p[]>=) p[]-=;
else if(p[]) p[]--;
else if(p[]&&p[]&&(p[]->=(p[]+p[]))) {p[]--; p[]++; p[]--;}
else if(p[]>=&&p[]) p[]--,p[]--,p[]++,p[]++;
else if(p[]>=&&p[]) p[]--,p[]--,p[]++;
else if(p[]&&p[]) {p[]--;p[]--;p[]++;}
else if(p[]) p[]--;
else if(p[]>=) p[]--;
p[]--;
now++;
}
while(p[]) {
if(p[]) p[]--;
else if(p[]) p[]--;
else if(p[]) { p[]--; p[]++;}
p[]--;
now++;
}
now+=(p[]+p[]+p[]);
ans=min(now,ans);
return;
} void dfs(int x,int now) {
while(!a[x]&&x<=) x++;
if(x+<=) dfs(x+,now);
if(x>=) { work(now); return ;} int i;
for(i=x;i<=;i++) {
if(!a[i]) break;
a[i]--;
if(i-x+>=) {
dfs(x,now+);
}
}
for(int j=i-;j>=x;j--) a[j]++; for(i=x;i<=;i++) {
if(a[i]<) break;
a[i]-=;
if(i-x+>=) {
dfs(x,now+);
}
}
for(int j=i-;j>=x;j--) a[j]+=; for(i=x;i<=;i++) {
if(a[i]<) break;
a[i]-=;
if(i-x+>=) {
dfs(x,now+);
}
}
for(int j=i-;j>=x;j--) a[j]+=;
} int main()
{
scanf("%d%d",&T,&n);
while(T--) {
ans=n;
for(int i=;i<=;i++) a[i]=;
for(int i=;i<=n;i++) {
int x,y;
scanf("%d%d",&x,&y);
if(x>=&&x<=) a[x-]++;
else if(x==) a[]++;
else if(x==) a[]++;
else if(y==) a[]++;
else a[]++;
}
dfs(,);
printf("%d\n",ans);
}
return ;
}

数据造福人类(洛谷数据,来自在下,ylg,llj,sxy)

【.in】

【.out】

【.in】

【.out】

【.in】

【.out】

普通

【.in】

【.out】

【.in】

【.out】

【.in】

【.out】

【.in】

【.out】

【.in】

【.out】

【.in】

【.out】

【.in】

【.out】

【.in】

【.out】

特殊

-------------------------------------------------

更新一组数据 来自ykkkkkkk

【44.in】
1 11
9 1
6 1
6 2
8 1
9 2
8 2
1 1
6 3
8 3
9 3
9 4
【44.out】
2

  

32.潜伏者

粘个openjudge上的代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <iomanip>
#include <cstring>
using namespace std;
char a[],b[],c[],d[];
int main()
{
int l1,l2,m=;
gets(a);
gets(b);
gets(c);
l1=strlen(a);
l2=strlen(c);
for(int i=;i<l1;i++)
for(int j=;j<l1;j++)
if((a[i]==a[j]&&b[i]!=b[j])||(a[i]!=a[j]&&b[i]==b[j])){cout<<"Failed";return ;}
for(int i=;i<l1;i++)
d[a[i]]++;
for(char i='A';i<='Z';i++)
if(d[i]== ){cout<<"Failed";return ;}
for(int i=;i<l2;i++)
for(int j=;j<l1;j++)
if(c[i]==a[j]){c[i]=b[j];break;}
puts(c);
return ; }

33.Hankson 的趣味题

水题。线筛预处理出质数,分解质因子,然后直接算答案。别忘了大于sqrt的质因子。

//Twenty
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
const int maxn=44725;
typedef long long LL;
using namespace std;
int T,p[maxn],bo[maxn],fl; LL a0,a1,b0,b1,aa0[4650],aa1[4650],bb0[4650],bb1[4650],ans; void get_prime() {
for(int i=2;i<=44722;i++) {
if(!bo[i]) {p[++p[0]]=i;}
for(int j=1;j<=p[0]&&p[j]*i<=44722;j++) {
bo[i*p[j]]=1;
if(i%p[j]==0) break;
}
}
} void work(LL x,LL y[]) {
for(int i=1;i<=p[0]&&p[i]<=x&&x!=1;i++) if(x%p[i]==0){
while(x%p[i]==0) {
y[i]++;
x/=p[i];
}
}
if(x!=1) y[4649]=x;
} int main()
{
get_prime();
scanf("%d",&T);
while(T--) {
for(int i=0;i<4650;i++) aa0[i]=aa1[i]=bb0[i]=bb1[i]=0;
ans=1LL; fl=0;
scanf("%lld%lld%lld%lld",&a0,&a1,&b0,&b1);
work(a0,aa0); work(b0,bb0);
work(a1,aa1); work(b1,bb1);
if(b1%a1!=0) fl=1;
for(int i=1;i<=p[0];i++) {
if(aa1[i]>bb1[i]) {fl=1; break;}
LL up=bb1[i],dn=aa1[i];
if(aa0[i]>aa1[i]) up=min(up,aa1[i]);
if(bb0[i]<bb1[i]) dn=max(dn,bb1[i]);
if(up<dn) {fl=1; break;}
ans*=(up-dn+1);
}
if(aa1[4649]>bb1[4649]) fl=1;
else if(bb1[4649]!=aa1[4649]) {
if(bb0[4649]==bb1[4649]) ans*=2;
}
if(fl) ans=0;
printf("%d\n",ans);
}
return 0;
}

  

34.最优贸易

裸的spfa,难得的一A,这年的题好像比较水啊,至少前三道都挺水。

//Twenty
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
typedef long long LL;
using namespace std;
const int maxn=100005;
const int maxm=500005*2;
int ans,x,y,z,n,m,ecnt,a[maxn],dz[maxn],df[maxn]; void read(int &ret) {
char ch=getchar(); ret=0;
while(ch<'0'||ch>'9') ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) ret=ret*10+ch-'0';
} int fir[maxn],nxt[maxm],to[maxm],fif[maxn],nxf[maxm],tf[maxm];
void add(int u,int v) {
nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
nxf[ecnt]=fif[v]; fif[v]=ecnt; tf[ecnt]=u;
} queue<int>que;
int vis[maxn];
void spfa(int fir[],int nxt[],int to[],int dis[],int s) {
que.push(s);
dis[s]=a[s];
vis[s]=1;
while(!que.empty()) {
int x=que.front();
que.pop(); vis[x]=0;
for(int i=fir[x];i;i=nxt[i]) {
int y=min(dis[x],a[to[i]]);
if(y<dis[to[i]]) {
dis[to[i]]=y;
if(!vis[to[i]]) {
vis[to[i]]=1;
que.push(to[i]);
}
}
}
}
} int main()
{
read(n); read(m);
for(int i=1;i<=n;i++) read(a[i]);
for(int i=1;i<=m;i++) {
read(x); read(y); read(z);
add(x,y); if(z==2) add(y,x);
}
memset(dz,127,sizeof(dz));
memset(df,127,sizeof(df));
spfa(fir,nxt,to,dz,1);
for(int i=1;i<=n;i++) a[i]=-a[i];
spfa(fif,nxf,tf,df,n);
for(int i=1;i<=n;i++) {
ans=max(ans,-df[i]-dz[i]);
}
printf("%d\n",ans);
return 0;
}

  

35.靶形数独

这一年的Noip题是目前做过的最简单的。

搜索,模拟数独每次找可能填的数最少的格子填数。

貌似时限是2s但洛谷只给了1s,codevs上轻松地A了跑得还挺快,洛谷上卡卡常也可以过。

比较迷的是24行那句剪枝加上就会T第三个点,这究竟是为什么呀QAQ

//Twenty
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
typedef long long LL;
using namespace std;
int tp,x,a[10][10],okx[10][10],oky[10][10],okz[10][10],ans,fl;
int v[10][10]={0,0,0,0,0,0,0,0,0,0,0,6,6,6,6,6,6,6,6,6,0,6,7,7,7,7,7,7,7,6,0,6,7,8,8,8,8,8,7,6,0,6,7,8,9,9,9,8,7,6,0,6,7,8,9,10,9,8,7,6,0,6,7,8,9,9,9,8,7,6,0,6,7,8,8,8,8,8,7,6,0,6,7,7,7,7,7,7,7,6,0,6,6,6,6,6,6,6,6,6}; int get(int x,int y) {
if(x%3) x=x/3+1; else x=x/3;
if(y%3) y=y/3+1; else y=y/3;
return (x-1)*3+y;
} void dfs(int rem,int now) {
if(rem==0) {fl=1; ans=max(ans,now); return;}
//if(now+rem*90<ans) return ;
int tx=0,ty=0,mi=10; for(register int i=1;i<=9;i++)
for(register int j=1;j<=9;j++) if(!a[i][j]) {
int tpp=9,zz=get(i,j);
for(register int k=1;k<=9;k++) {
if(okx[i][k]||oky[j][k]||okz[zz][k]) tpp--;
}
if(tpp<mi||tpp==mi) mi=tpp,tx=i,ty=j;
}
int tz=get(tx,ty);
for(register int i=1;i<=9;i++) if(!okx[tx][i]&&!oky[ty][i]&&!okz[tz][i]) {
a[tx][ty]=i;
okx[tx][i]=1; oky[ty][i]=1; okz[tz][i]=1;
dfs(rem-1,now+a[tx][ty]*v[tx][ty]);
okx[tx][i]=0; oky[ty][i]=0; okz[tz][i]=0;
a[tx][ty]=0;
}
} int main()
{
tp=9*9;
for(register int i=1;i<=9;i++)
for(register int j=1;j<=9;j++) {
scanf("%d",&x);
if(x) {
tp--;
ans+=x*v[i][j];
a[i][j]=x;
okx[i][x]=1;
oky[j][x]=1;
okz[get(i,j)][x]=1;
}
}
dfs(tp,ans);
if(fl) {
printf("%d\n",ans);
}
else printf("-1\n");
return 0;
}

  

【noip】跟着洛谷刷noip题的更多相关文章

  1. 【noip】跟着洛谷刷noip题2

    noip好难呀. 上一个感觉有点长了,重开一个. 36.Vigenère 密码 粘个Openjudge上的代码 #include<cstdio> #include<iostream& ...

  2. 洛谷模拟NOIP考试反思

    洛谷模拟NOIP考试反思 想法 考了这么简单的试qwq然而依然emmmmmm成绩不好 虽然本次难度应该是大于正常PJ难度的但还是很不理想,离预估分数差很多qwq 于是就有了本反思嘤嘤嘤 比赛链接 原比 ...

  3. [NOIP提高&洛谷P1024]一元三次方程求解 题解(二分答案)

    [NOIP提高&洛谷P1024]一元三次方程求解 Description 有形如:ax3+bx2+cx+d=0 这样的一个一元三次方程.给出该方程中各项的系数(a,b,c,d 均为实数),并约 ...

  4. 洛谷 P3951 NOIP 2017 小凯的疑惑

    洛谷 P3951 NOIP 2017 小凯的疑惑 题目描述 小凯手中有两种面值的金币,两种面值均为正整数且彼此互素.每种金币小凯都有 无数个.在不找零的情况下,仅凭这两种金币,有些物品他是无法准确支付 ...

  5. 洛谷P5274 优化题(ccj)

    洛谷P5274 优化题(ccj) 题目背景 CCJCCJ 在前往参加 Universe \ OIUniverse OI 的途中... 题目描述 有一个神犇 CCJCCJ,他在前往参加 Universe ...

  6. 洛谷 P4148 简单题 KD-Tree 模板题

    Code: //洛谷 P4148 简单题 KD-Tree 模板题 #include <cstdio> #include <algorithm> #include <cst ...

  7. 洛谷P1006 NOIP提高组2008 传纸条

    P1006 传纸条 题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n 列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无 ...

  8. NOIP 2016 洛谷 P2827 蚯蚓 题解

    题目传送门 展开 题目描述 本题中,我们将用符号[c]表示对c向下取整,例如:[3.0」= [3.1」=[3.9」=3.蛐蛐国最近蚯蚓成灾了!隔壁跳 蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手 ...

  9. 【AC自动机】洛谷三道模板题

    [题目链接] https://www.luogu.org/problem/P3808 [题意] 给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过. [题解] 不再介绍基础知识了,就是裸的模 ...

随机推荐

  1. ADS 下 flash 烧写程序原理及结构

    本原理:在 windows 环境下借助 ADS 仿真器将在 SDRAM 中的一段存储区域中的数据写到 Nand flash 存 储空间中.烧写程序在纵向上分三层完成: 第一层: 主烧写函数(完成将在 ...

  2. 算法系列:Shell 排序

    Copyright © 1900-2016, NORYES, All Rights Reserved. http://www.cnblogs.com/noryes/ 欢迎转载,请保留此版权声明. -- ...

  3. odoo js

    1.相关库/框架 主要:jQuery(使用1.8.3,如果使用新版本,其他jQuery插件也要升级或修改).Underscore.QWeb 其他:都在addons\web\static\lib路径下. ...

  4. [JZOJ4673] 【NOIP2016提高A组模拟7.20】LCS again

    题目 描述 题目大意 给你一个字符串和字符的取值范围,问和这个字符串的最长公共子串的长度为N−1N-1N−1的串的个数. 思考历程 一看就知道这是一个神仙题. 思考了一会儿,觉得AC是没有希望的了. ...

  5. hibernate抓取策略

    抓取策略(fetching strategy) 是指:当应用程序需要在(Hibernate实体对象图的)关联关系间进行导航的时候, Hibernate如何获取关联对象的策略.抓取策略可以在O/R映射的 ...

  6. 更改git提交显示的用户名

    问题描述 同一项目多人开发难免会用到版本控制,最为流行的当属git.开发中出现一个小问题,每个人提交后显示的用户名,如下图 组长发话:把用户名都改成自己的名字! 这时发现用户名并不是自己的名字,怎么改 ...

  7. vue-cli的使用指南

    vue-cli 2.0 安装vue-cli npm install -g vue-cli 创建一个项目模板 vue init <template-name> <project-nam ...

  8. springboot思维导图

  9. 2014-VGG-《Very deep convolutional networks for large-scale image recognition》翻译

    2014-VGG-<Very deep convolutional networks for large-scale image recognition>翻译 原文:http://xues ...

  10. windows 遍历目录下的所有文件 FindFirstFile FindNextFile

    Windows下遍历文件时用到的就是FindFirstFile 和FindNextFile 首先看一下定义: HANDLE FindFirstFile( LPCTSTR lpFileName, // ...