2018.9.27 练习赛 动态规划专练

T1 碎片

题解:

状压集合\(DP\),状态\(F[s]\),表示完成\(s\)这个集合的填充最少需要多少步,预先预处理,将所有回文串标记为\(true\)\(DP\)时外循环枚举0-全集,内循环枚举外循环的补集的子集;

\(code\):

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector> 
#include<ctype.h>
#define inf 1e9+9
#define ll long long
using namespace std;

char buf[1<<20],*p1,*p2;
inline char gc()
{
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}

template<typename T>
inline void read(T &x)
{
	char tt;
	bool flag=0;
	while(!isdigit(tt=gc())&&tt!='-');
	tt=='-'?(x=0,flag=1):(x=tt-'0');
	while(isdigit(tt=gc())) x=x*10+tt-'0';
	if(flag) x=-x;
}

int n,tot;
int f[1<<17];
bool book[1<<17];
char a[20];
char tmp1[20],tmp2[20];
bool ok(int s)
{
	int cnt=0,now=0;
	while(s)
	{
		now++;
		if(s&1) tmp1[++cnt]=a[now];
		s>>=1;
	}
	for(int i=cnt;i>=1;i--)
	tmp2[cnt-i+1]=tmp1[i];
	for(int i=1;i<=cnt;i++)
	if(tmp1[i]!=tmp2[i]) return 0;
	return 1;
}

int main()
{
	freopen("piece.in","r",stdin);
	freopen("piece.out","w",stdout);
	char tt;
	while((tt=gc())!='\n') a[++n]=tt;
	tot=(1<<n)-1;
	for(int i=1;i<=tot;i++) f[i]=inf;
	for(int s=1;s<=tot;s++)
	if(ok(s)) book[s]=1;
	for(int s1=0;s1<=tot;s1++)
	{
		int s=s1^tot;
		for(int s2=s;s2;s2=(s2-1)&s)
		{
			if(!book[s2]) continue;
			f[s1|s2]=min(f[s1|s2],f[s1]+1);
		}
	}
	printf("%d",f[tot]);
}

T2 龙珠

题解:

优化\(DP\),状态很好想\(F[i][j]\),表示第n秒停在m号位置可以消耗的最少体力,状态转移:\(F[i][j]=min{F[i][j],F[i-1][k]+pos+cost},(1<=k<=m)\),显然时间复杂度为\(O(N*M^2)\),对取最小值进行优化,打开绝对值,分为两个单调队列或优先队列讨论;

\(code:\)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<ctype.h>
#define inf 1e9+9
#define ll long long
using namespace std;

char buf[1<<20],*p1,*p2;
inline char gc() {
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}

template<typename T>
inline void read(T &x) {
	char tt;
	bool flag=0;
	while(!isdigit(tt=gc())&&tt!='-');
	tt=='-'?(x=0,flag=1):(x=tt-'0');
	while(isdigit(tt=gc())) x=x*10+tt-'0';
	if(flag) x=-x;
}

int n,m,x,ans,f[55][5005];
struct node {
	int pos,cost;
	inline node(int a=0,int b=0) {
		pos=a;
		cost=b;
	}
	bool operator<(node a)const {
		return pos<a.pos;
	}

} a[55][5005];

int main() {
	freopen("dragon.in","r",stdin);
	freopen("dragon.out","w",stdout);
	read(n),read(m),read(x);
	for(int i=1; i<=n; i++ )
	for(int j=1; j<=m; j++ )
	read(a[i][j].pos);

	for(int i=1; i<=n; i++)
	for(int j=1; j<=m; j++)
	read(a[i][j].cost);

	for(int i=1; i<=n; i++) sort(a[i]+1,a[i]+m+1);
	for(int j=1; j<=m; j++)
	f[1][j]=abs(x-a[1][j].pos)+a[1][j].cost;

	for(int i=2; i<=n; i++ ) {
	ans=inf;
	for(int j=1,k=1; j<=m; j++ ) 
	{
		for( ;k<=m&&a[i-1][k].pos<=a[i][j].pos; k++ ) 
		{
			int t=f[i-1][k]-a[i-1][k].pos;
				ans=min(ans,t);
		}
		f[i][j]=ans+a[i][j].pos+a[i][j].cost;
	}

		ans=inf;
		for(int j=m,k=m; j; j-- ) {
		for(; k&&a[i-1][k].pos>a[i][j].pos; k--) 
			{
				int t=f[i-1][k]+a[i-1][k].pos;
				ans=min(ans,t);
			}
			f[i][j]=min(f[i][j],ans-a[i][j].pos+a[i][j].cost);
		}
	}

	ans=inf;
	for(int j=1; j<=m; j++) ans=min(ans,f[n][j] );
	printf("%d",ans);
}

T3 仓库

题解:

树形\(DP\),\(30\)分做法是\(N^2\)爆搜,\(50\)分做法为\(O(N)\)处理类似最大深度和问题,\(100\)分做法待补;

\(30\)\(code:\)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector> 
#include<ctype.h>
#define ll long long
using namespace std;

char buf[1<<20],*p1,*p2;
inline char gc()
{
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}

template<typename T>
inline void read(T &x)
{
	char tt;
	bool flag=0;
	while(!isdigit(tt=gc())&&tt!='-');
	tt=='-'?(x=0,flag=1):(x=tt-'0');
	while(isdigit(tt=gc())) x=x*10+tt-'0';
	if(flag) x=-x;
}

struct node{
	ll x,len;
	inline node(ll a=0,ll b=0)
	{
		x=a;
		len=b;
	}
	inline bool operator<(node a)const
	{
		return len<a.len;
	}
};

ll n,m;
ll sz[10005],f[10005];
vector<node>G[10005];

void dfs(ll x,ll pre,ll dis)
{
	f[x]=dis;
	for(int i=G[x].size()-1;i>=0;i--)
	{
		int p=G[x][i].x;
		int len=G[x][i].len;
		if(p==pre) continue;
		dfs(p,x,dis+len);
	}
}

int main()
{
	freopen("warehouse.in","r",stdin);
	freopen("warehouse.out","w",stdout);
	read(n),read(m);
	for(int i=1;i<n;i++)
	{
		ll x,y,z;
		read(x),read(y),read(z);
		G[x].push_back(node(y,z));
		G[y].push_back(node(x,z));
	}
	for(int i=1;i<=n;i++)
	{
		memset(f,0,sizeof(f));
	 	ll ans=0;
		dfs(i,0,0);
		for(int j=1;j<=n;j++)
		if(i!=j) ans+=(f[j]^m);
		printf("%lld\n",ans);
	}
}

posted @ 2018-09-28 14:45  Katoumegumi  阅读(74)  评论(0编辑  收藏  举报
返回顶部