动规专题测试

题目 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值