题目 A: 公交换乘
01背包(大水题)
#include<bits/stdc++.h>
#define re return
#define st static
#define Min(a,b) (a)<(b)?(a):(b)
#define Max(a,b) (a)>(b)?(a):(b)
#define inc(i,l,r) for(int i=l;i<=r;++i)
#define dec(i,l,r) for(int i=l;i>=r;--i)
#define mem(a,b) memset((a),(b),sizeof(a))
using namespace std;
int n,v[15],f[205];
int main()
{
// freopen("in.txt","r",stdin);
inc(i,1,10)scanf("%d",&v[i]);
scanf("%d",&n);
mem(f,0x3f3f3f3f);
f[0]=0;
inc(i,1,n)inc(j,1,10)
if (j>i)break;
else f[i]=Min(f[i],f[i-j]+v[j]);
printf("%d",f[n]);
re 0;
}
题目 B: 数字矩形
有点小坑,左右皆有来源
#include<bits/stdc++.h>
#define re return
#define st static
#define Min(a,b) (a)<(b)?(a):(b)
#define Max(a,b) (a)>(b)?(a):(b)
#define inc(i,l,r) for(int i=l;i<=r;++i)
#define dec(i,l,r) for(int i=l;i>=r;--i)
#define mem(a,b) memset((a),(b),sizeof(a))
using namespace std;
long long ans=9999999999999,n,m,v[105][505],f[105][505];
int main()
{
// freopen("in.txt","r",stdin);
scanf("%lld%lld",&n,&m);
inc(i,1,n)
{
f[i][0]=f[i][m+1]=0x3f3f3f3f;
inc(j,1,m)
scanf("%lld",&v[i][j]);
}
inc(j,1,m)f[1][j]=v[1][j];
inc(i,2,n)
{
inc(j,1,m)
f[i][j]=v[i][j]+min(f[i-1][j],f[i][j-1]);
dec(j,m,1)//逆序
f[i][j]=min(f[i][j],f[i][j+1]+v[i][j]);
//左右分开跑
}
inc(j,1,m)ans=min(ans,f[n][j]);
printf("%lld",ans);
re 0;
}
一位大佬的玄学做法,蒟蒻正在努力看懂中ing…
#include<bits/stdc++.h>
using namespace std;
#define go(i,a,b) for(register int i=(a);i<=(b);++(i))
#define come(i,a,b) for(register int i=(a);i>=(b);--(i))
#define mem(a,b) memset((a),(b),sizeof(a))
#define ll long long
#define inf 0x3f3f3f3f
#define fre freopen("input.txt","r",stdin)
ll g[105][505],num[105][505],f[105][505];
void read(ll &x)
{
int f=1;char s=getchar();x=0;
while(!isdigit(s))
{
if(s=='-')
f=-1;
s=getchar();
}
while(isdigit(s))
{
x=(x<<3)+(x<<1)+s-'0';
s=getchar();
}
x*=f;
}//读入优化
int main()
{
//fre;
int n,m;
scanf("%d%d",&n,&m);
go(i,1,n) go(j,1,m) read(g[i][j]);
go(i,1,n)
go(j,1,m)
{
num[i][j]=num[i][j-1]+g[i][j];
}
go(i,1,m) f[1][i]=g[1][i];
go(i,2,n)
{
go(j,1,m)
go(k,1,m)
{
ll delta;
if(j<k) delta=num[i][k]-num[i][j]+g[i][j];
else delta=num[i][j]-num[i][k]+g[i][k];
if(!f[i][j])
f[i][j]=delta+f[i-1][k];
else
f[i][j]=min(f[i][j],delta+f[i-1][k]);
}
}
ll ans=f[n][1];
go(i,2,m) ans=min(ans,f[n][i]);
printf("%lld",ans);
return 0;
}
蒟蒻40分dfs
#include<bits/stdc++.h>
#define re return
#define st static
#define Min(a,b) (a)<(b)?(a):(b)
#define Max(a,b) (a)>(b)?(a):(b)
#define inc(i,l,r) for(int i=l;i<=r;++i)
#define dec(i,l,r) for(int i=l;i>=r;--i)
#define mem(a,b) memset((a),(b),sizeof(a))
using namespace std;
long long a,x,t,d,n,vis[15],use[15],vi[15],pi[15]={1,1,2,6,24,120,720,5040,40320,362880};
char s[15];
void dfs(long long sum,int deep)
{
if(deep==n)
{
if(!(sum%d))a++;
re;
}
inc(i,0,n-1)
if(!vis[i])
{
vis[i]=1;
dfs((sum<<3)+(sum<<1)+vi[i],deep+1);
vis[i]=0;
}
}
int main()
{
// freopen("in.txt","r",stdin);
scanf("%lld",&t);
while(t--)
{
a=0,x=1;
mem(use,0);
scanf("%s%lld",s,&d);
n=strlen(s);
inc(i,0,n-1)
use[vi[i]=s[i]^48]++;
dfs(0,0);
inc(i,0,9)
x*=pi[use[i]];
printf("%lld\n",a/x);
}
re 0;
}
可拿50de区间函数next_permutation
#include <bits/stdc++.h>
using namespace std;
const int MAXN=15;
int t,n,d;
long long ans;
int num[MAXN];
char str[MAXN];
inline int read()
{
int X=0;
char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
return X;
}
int main()
{
// freopen("input.txt","r",stdin);
t=read();
while(t--)
{
scanf("%s%d",str,&d);
n=strlen(str);
for(int i=0;i<n;i++) num[i+1]=str[i]-'0';
sort(num+1,num+n+1);
ans=0;
do
{
long long s=0;
for(int i=1;i<=n;i++)
s=(s<<1)+(s<<3)+num[i];
if(s%d==0)
ans++;
}while(next_permutation(num+1,num+n+1));
printf("%lld\n",ans);
}
}
LRL 大佬50分dfs
#define ri register int
#define ll long long
#define rep(i,a,b) for(register int i=(a);i<=(b);++i)
#define dwn(i,a,b) for(register int i=(a);i>=(b);--i)
#define ee(i,a) for(register int i=head[a];i;i=e[i].nxt)
#include<bits/stdc++.h>
using namespace std;
const int N=1055;
const int M=2055;
const int inf=0x3f3f3f3f;
/*char ss[1<<21],*A=ss,*B=ss;
inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<21,stdin),A==B)?EOF:*A++;}
template<class T>void rd(T&x){
ri f=1;char c=gc();x=0;while(c<48||c>57){if(c=='-')f=-1;c=gc();};
while(c>47&&c<58){x=(x<<3)+(x<<1)+(c^48);c=gc();}x*=f;
}*/
int /*bj1[105],bj2[105],bj3[105],bj4[105],bj5[105],*/vis[555],a[15],cnt;
ll ans,d;
char s[5555];
void dfs(ll num,int step,int maxh){
if(step==maxh){
/*ll t1=(num/100)%100,t2=(num/10000)%100,t3=(num/1000000)%100,t4=num/100000000,t5=num%100;
if(num%d==0&&!(bj1[t1]&&bj2[t2]&&bj3[t3]&&bj4[t4]&&bj5[t5])){
bj1[t1]=1;bj2[t2]=1;bj3[t3]=1;bj4[t4]=1;bj5[t5]=1;
++ans;
} */
if(num%d==0)++ans;
return;
}
rep(i,1,cnt){
if(vis[a[i]]){
//num=(num<<1)+(num<<3)+s[i]-'0';
num=(num<<1)+(num<<3)+a[i];
vis[a[i]]--;
dfs(num,step+1,maxh);
vis[a[i]]++;
num/=10;
}
}
}
int main()
{
//freopen("read.txt","r",stdin);
int T;scanf("%d\n",&T);
while(T--){
scanf("%s %lld\n",s+1,&d);
int len=strlen(s+1);
ans=0;cnt=0;
rep(i,0,9)vis[i]=-1;
rep(i,1,len){
if(vis[s[i]-'0']==-1){
a[++cnt]=s[i]-'0';
vis[s[i]-'0']=1;
}
else vis[s[i]-'0']++;
}
/*rep(i,0,101){
bj1[i]=0;bj2[i]=0;bj3[i]=0;bj4[i]=0;bj5[i]=0;
} */
dfs(0,0,len);
printf("%lld\n",ans);
}
return 0;
}
小生100pts状压已码好
#include<bits/stdc++.h>
#define re return
#define st static
#define mem(a,b) memset((a),(b),sizeof(a))
#define inc(i,l,r) for(int i=l;i<=r;++i)
#define dec(i,l,r) for(int i=l;i>=r;--i)
using namespace std;
template<typename T>inline void read(T&x)
{
char c;bool f=0;
while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
x=c^48;
while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
if(f)x=-x;
}
int t,mod,f[8200][1005],v[15],use[15],pi[15]={1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600};
//f[s][yu]:s是指哪些位置上数选了,yu则是余数;f则是这种状态下个数
char s[15];
int main()
{
freopen("in.txt","r",stdin);
read(t);
while(t--)
{
scanf("%s%d",s,&mod);
int n=strlen(s),x=1,maxn;
mem(use,0);
inc(i,0,n-1)use[v[i]=s[i]^48]++;
maxn=(1<<n)-1;//二进制,所有数全选了
inc(i,0,maxn)inc(j,0,mod)f[i][j]=0;
f[0][0]=1;//赋初值,一个也不选余数为0情况自然为一
inc(i,0,maxn-1)inc(k,0,mod-1)
if(f[i][k])inc(j,0,n-1)
if(!(i&(1<<j)))//如果i没有选j
f[i|(1<<j)][(k*10+v[j])%mod]+=f[i][k];
//f[i选j状态][余数(k*10+v[j]:j加在后面没错,
//因为每种状态都会遍历)]
inc(i,0,9)x*=pi[use[i]];//全排列去重,请自行模拟并理解
printf("%d\n",f[maxn][0]/x);
}
re 0;
}

161

被折叠的 条评论
为什么被折叠?



