学校食堂
题目描述
小F的学校在城市的一个偏僻角落,所有学生都只好在学校吃饭。学校有一个食堂,虽然简陋,但食堂大厨总能做出让同学们满意的菜肴。当然,不同的人口味也不一定相同,但每个人的口味都可以用一个非负整数表示。
由于人手不够,食堂每次只能为一个人做菜。做每道菜所需的时间是和前一道菜有关的,若前一道菜的对应的口味是a,这一道为b,则做这道菜所需的时间为(a or b)-(a and b),而做第一道菜是不需要计算时间的。其中,or和and表示整数逐位或运算及逐位与运算,C语言中对应的运算符为”|”和”&”。
学生数目相对于这个学校还是比较多的,吃饭做菜往往就会花去不少时间。因此,学校食堂偶尔会不按照大家的排队顺序做菜,以缩短总的进餐时间。
虽然同学们能够理解学校食堂的这种做法,不过每个同学还是有一定容忍度的。也就是说,队伍中的第i个同学,最多允许紧跟他身后的Bi个人先拿到饭菜。一旦在此之后的任意同学比当前同学先拿到饭,当前同学将会十分愤怒。因此,食堂做菜还得照顾到同学们的情绪。
现在,小F想知道在满足所有人的容忍度这一前提下,自己的学校食堂做完所有菜最少需要多少时间。
输入格式
第一行包含一个正整数C,表示测试点的数据组数。
每组数据的第一行包含一个正整数N,表示同学数。
每组数据的第二行起共N行,每行包含两个用空格分隔的非负整数Ti和Bi,表示按队伍顺序从前往后的每个同学所需的菜的口味和这个同学的忍受度。
每组数据之间没有多余空行。
输出格式
包含C行,每行一个整数,表示对应数据中食堂完成所有菜所需的最少时间。
很变态的一道动态规划题。
f[i][j][k]表示前 i-1 个同学排好了队,排在最后面的人是 k ,j 表示 i 以及 i 后面几个人的状态,状态压缩。
1 气得我吐血啊! 2 查了一晚上的错,原来是位运算 (1<<x)-1与1<<x-1是不同的啊! 3 4 #include<iostream> 5 #include<fstream> 6 #define NUM 100000000 7 using namespace std; 8 //ifstream fin("cin.in"); 9 10 int t,n,f[1010][1<<8][20],v[1010],b[1010]; 11 12 int count(int a,int b){ 13 if (a <= 0) return 0; 14 return v[a]^v[b]; 15 } 16 void min(int &a, int b){ 17 if (b < a) a = b; 18 } 19 20 int main() 21 { 22 cin>>t; 23 24 while(t>0) 25 { 26 t--; 27 cin>>n; 28 29 for(int i=1;i<=n;++i) 30 cin>>v[i]>>b[i]; 31 32 memset(f,0x7f,sizeof(f)); 33 f[1][(1<<8)-1][7]=0; 34 35 for(int i=1;i<=n;++i) 36 for(int j=(1<<8)-1;j>=0;--j) 37 for(int k=-8;k<=7;++k) 38 { 39 if ((j&1)==0) min(f[i+1][(j>>1)|(1<<7)][k-1+8],f[i][j][k+8]); 40 else { 41 int ma=NUM; 42 for(int l=0;l<=7;++l) 43 if ((j>>l)&1) 44 { 45 if (i + l > ma) break; 46 min(ma, i + l + b[i + l]); 47 min(f[i][j&~(1<<l)][l+8],f[i][j][k+8]+count(i+k,i+l)); 48 } 49 } 50 } 51 52 int ans=NUM; 53 for(int i=-8;i<=-1;++i) 54 min(ans,f[n+1][(1<<8)-1][i+8]); 55 cout<<ans<<endl; 56 // system("pause"); 57 } 58 return 0; 59 }