zoukankan      html  css  js  c++  java
  • [JSOI2010]快递服务

    I.[JSOI2010]快递服务

    我们约定共有\(n\)个地点,依次登记了\(m\)家公司。

    思路1.

    \(f[l][i][j][k]\)表示:当前某一个司机在第\(i\)家公司(注意是公司!\(1000\)家那个!),第二个司机在第\(j\)家,第三个司机在第\(k\)家,当前我们遍历到了第\(l\)家公司。依次转移即可。

    复杂度\(O(m^4)\)

    思路2.观察到\(i,j,k\)中必有一个等于\(l\)(不然你位置\(l\)的货是哪辆车发的?),因此我们可以省掉一维。设\(f[i][j][k]\)即可。

    复杂度\(O(m^3)\)

    明显第一维可以滚动掉,因此空间复杂度便可以通过。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n,dis[210][210],f[2][1010][1010],pos[1010],m,res=0x3f3f3f3f;
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%d",&dis[i][j]);
    	memset(f,0x3f3f3f3f,sizeof(f)),f[1][2][1]=0;
    	pos[++m]=1,pos[++m]=2,pos[++m]=3;
    	while(scanf("%d",&pos[++m])!=EOF);
    	for(int i=3;i<m;i++){
    		for(int j=1;j<=i;j++)for(int k=1;k<j;k++)f[!(i&1)][j][k]=0x3f3f3f3f;
    		for(int j=1;j<i;j++)for(int k=1;k<j;k++){
    			f[!(i&1)][j][k]=min(f[!(i&1)][j][k],f[i&1][j][k]+dis[pos[i]][pos[i+1]]);
    			f[!(i&1)][i][k]=min(f[!(i&1)][i][k],f[i&1][j][k]+dis[pos[j]][pos[i+1]]);
    			f[!(i&1)][i][j]=min(f[!(i&1)][i][j],f[i&1][j][k]+dis[pos[k]][pos[i+1]]);
    		}
    //		for(int j=1;j<=i;j++){for(int k=1;k<j;k++)printf("%d ",f[!(i&1)][j][k]);puts("");}puts("");
    	}
    	for(int j=1;j<m;j++)for(int k=1;k<j;k++)res=min(res,f[m&1][j][k]);
    	printf("%d\n",res);
    	return 0;
    } 
    

    思路3.发现\(O(m^3)\)只能拿到\(50\%\)。似乎只有最后两维可以优化成\(n^2\)的。

    我们设\(f[i][j][k]\)表示:当前某一辆车在第\(i\)公司(还是\(1000\)家那个!)剩下两辆车分别在第\(j\)和第\(k\)收件地点(是\(200\)家那个!)。

    复杂度为\(O(mn^2)\)

    这是正解尽管出题人丧心病狂卡长只有\(70\%\)但是开个\(O3\)然后卡卡长就过了

    代码:

    #pragma GCC optimize(3)
    #include<bits/stdc++.h>
    using namespace std;
    int n,dis[210][210],f[2][1010][1010],pos[1010],m,res=0x3f3f3f3f;
    inline void read(int &x){
    	x=0;
    	register char c=getchar();
    	while(c>'9'||c<'0')c=getchar();
    	while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
    }
    inline void print(int x){
    	if(x<=9)putchar('0'+x);
    	else print(x/10),putchar('0'+x%10);
    }
    int main(){
    	read(n);
    	for(register int i=1;i<=n;i++)for(register int j=1;j<=n;j++)read(dis[i][j]);
    	memset(f,0x3f3f3f3f,sizeof(f)),f[1][2][1]=0;
    	pos[++m]=1,pos[++m]=2,pos[++m]=3;
    	while(scanf("%d",&pos[++m])!=EOF);
    	for(register int i=3;i<m;i++){
    		for(register int j=1;j<=n;j++)for(register int k=1;k<=n;k++)f[!(i&1)][j][k]=0x3f3f3f3f;
    		for(register int j=1;j<=n;j++)for(register int k=1;k<=n;k++){
    			f[!(i&1)][j][k]=min(f[!(i&1)][j][k],f[i&1][j][k]+dis[pos[i]][pos[i+1]]);
    			f[!(i&1)][pos[i]][k]=min(f[!(i&1)][pos[i]][k],f[i&1][j][k]+dis[j][pos[i+1]]);
    			f[!(i&1)][pos[i]][j]=min(f[!(i&1)][pos[i]][j],f[i&1][j][k]+dis[k][pos[i+1]]);
    		}
    //		for(int j=1;j<=i;j++){for(int k=1;k<j;k++)printf("%d ",f[!(i&1)][j][k]);puts("");}puts("");
    	}
    	for(register int j=1;j<=n;j++)for(register int k=1;k<=n;k++)res=min(res,f[m&1][j][k]);
    	print(res);
    	return 0;
    } 
    
  • 相关阅读:
    Android中内容观察者的使用 ContentObserver类详解 (转)
    Spinner
    对话框
    ButtonBar 的使用
    EditText/RadioButton/CheckBox使用
    ListView
    PieChar,此代码参考网上
    ComboBox中使用事件
    ColorPicker
    Button
  • 原文地址:https://www.cnblogs.com/Troverld/p/14596745.html
Copyright © 2011-2022 走看看