mobile service:滚动数组的使用

……并不是什么非常难的题目。

1.f[i][x][y][z]表示在第i轮,三个人分别在x,y,z的最小代价。

2.然而我们经过思考发现这样设计状态不是很好。在第i轮,一定有一个售货员在s[i]的位置,而且我们并不需要知道这三个人分别在哪个位置(就是ABC只要不在同一位置,所有状态都是一样的)。所以,我们可以缩减一维,f[i][x][y]表示第i轮,有2个人分别在x,y,另外一个人在s[i]。而状态也很好转移。。。就是枚举一下每一轮分别是哪个人跑到s[i]去。

3.然而我们发现空间不够用了emmm,所以考虑一下滚动数组。

然后我很悲伤的调了2个小时还不对。。。

血的教训:滚动数组一定一定要在使用之前清0!!!

#include <bits/stdc++.h>

using namespace std;
const int maxn=1005;
int l,n,c[205][205],s[maxn];
int f[3][205][205];
int main()
{
	scanf("%d%d",&l,&n);
	for(int i=1;i<=l;i++)
	{
		for(int j=1;j<=l;j++)
		{
			scanf("%d",&c[i][j]);	
		}
	}
	for(int i=1;i<=n;i++) scanf("%d",&s[i]);
	memset(f,0x3f,sizeof(f));
	f[1][2][3]=f[1][3][2]=c[1][s[1]];
	f[1][1][3]=f[1][3][1]=c[2][s[1]];
	f[1][1][2]=f[1][2][1]=c[3][s[1]];
	int now=0;
	for(int i=1;i<n;i++)
	{
		now^=1;
	//	cout<<now<<endl;
		memset(f[now^1],0x3f,sizeof(f[now^1]));//这一行超级重要啊 
		for(int x=1;x<=l;x++)
		{
			for(int y=1;y<=l;y++)
			{
			//	if(x==s[i+1]||y==s[i+1]) continue;
			if(x!=s[i+1]&&y!=s[i+1]&&x!=y) f[now^1][x][y]=min(f[now^1][x][y],f[now][x][y]+c[s[i]][s[i+1]]);
			if(s[i]!=s[i+1]&&y!=s[i+1]&&s[i]!=y) f[now^1][s[i]][y]=min(f[now^1][s[i]][y],f[now][x][y]+c[x][s[i+1]]);
			if(x!=s[i+1]&&s[i]!=s[i+1]&&x!=s[i]) f[now^1][x][s[i]]=min(f[now^1][x][s[i]],f[now][x][y]+c[y][s[i+1]]);
	//		cout<<f[now][x][y]<<" ";
			}
		}
	}
	int minv=0x3f3f3f3f;
	for(int x=1;x<=l;x++)
	{
		if(x==s[n]) continue;
		for(int y=1;y<=l;y++)
		{
			if(y==s[n]) continue;
			minv=min(minv,f[now^1][x][y]);
		}
	}
	printf("%d",minv); 
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章