标签:
题目分析:yy出奇迹,就拿每本书第一次出现的序列作为最终的序列然后按顺序模拟一下,
后来仔细思考了一下理解了这样做的正确性,其实也挺好理解的,
先看一个序列1 1 1 1 1 1 1 2,对于这个序列,我们很明显的策略是按1 2来排,
因为看过以后放在最上面,所以每次读1都不用搬书,对于一个阅读序列的子序列a b,
我们有两种排法,按a b排代价是w[b],按b a排代价是w[a] + w[b],
而且要明确的一点是确定了顺序,代价也就随之确定了,我们再将这个性质推广到一般得出贪心结论:
拿每本书第一次出现的顺序作为初始序列,比如1 1 3 1 1 3 2 1 1
按此策略得到的初始序列为1 3 2,不管初始序列是什么样的,
读完 1 1 3以后的书的顺序肯定都是确定的都为3 1 2,但是只有初始序列为1 3 2时得到3 1 2的代价最小,
其实还是要自己理解理解~
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 int w[505], b[1005]; 5 bool vis[505]; 6 int main() 7 { 8 int n, m, ans = 0; 9 scanf("%d %d", &n, &m); 10 for(int i = 1; i <= n; i++) 11 scanf("%d", &w[i]);//the weight of each book. 12 for(int i = 1; i <= m; i++) 13 scanf("%d", &b[i]);// the order of books that he would read 14 for(int i = 2; i <= m; i++) 15 { 16 memset(vis, false, sizeof(vis)); 17 for(int j = i - 1; j > 0; j--) 18 { 19 if(b[j] == b[i]) //只要找同一本书读到两次之间的书 20 break; 21 //对于其上面的书,我只关心它们的总重量,比如1 2 3 2 3 1 22 //我只关心第二次读到1时它上面有哪些书和它们的重量即w[2] + w[3] 23 //这里用个vis标记一下重复的即可 24 if(!vis[b[j]]) 25 { 26 ans += w[b[j]]; 27 vis[b[j]] = true; 28 } 29 } 30 } 31 printf("%d\n", ans); 32 }
CF 500 C New Year Book Reading
标签:
原文地址:http://www.cnblogs.com/123tang/p/5900300.html