Doing Homework again HDU 1789
可以用贪心做(网上搜了发现都是用贪心,DP就这么难???)
思路:the reduced scores.从大到小排序,(相同就把the deadlines of the subjects从小到大排序)
这里可保证耗分数最多的给完成,留下的分数最低。
其实这贪心很容易想到。但最坑的是!只给出一个N,我还以为the deadlines of the subjects就在这里取呢!(1~N)
之后才发现天数和所扣的分数未知!
幸好这个天数就在1000左右,如果在大点肯定超时!
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 #include<string.h> 5 using namespace std; 6 struct line 7 { 8 int x; 9 int y; 10 }a[1005]; 11 bool comp1(line i,line j) 12 { 13 if(i.y!=j.y) 14 return i.y>j.y; 15 return i.x<j.x; 16 } 17 int main() 18 { 19 int n,i,t,sum,d,b[1005]; 20 scanf("%d",&t); 21 while(t--) 22 { 23 scanf("%d",&n); 24 memset(b,0,sizeof(b)); 25 for(i=1;i<=n;i++) 26 scanf("%d",&a[i].x); 27 for(i=1;i<=n;i++) 28 scanf("%d",&a[i].y); 29 sort(a+1,a+1+n,comp1); 30 sum=0; 31 for(i=1;i<=n;i++) 32 { 33 d=0; 34 if(b[a[i].x]==0) 35 b[a[i].x]=1; 36 else 37 { 38 while(b[a[i].x]==1) 39 { 40 a[i].x--; 41 if(b[a[i].x]==0&&a[i].x>=1) 42 {b[a[i].x]=1;d=1;break;} 43 if(a[i].x<1) 44 break; 45 } 46 if(d==0) 47 sum+=a[i].y; 48 } 49 } 50 printf("%d ",sum); 51 } 52 return 0; 53 }
Brave Game HDU 1846
这道博弈题还是好找规律的:
巴什博弈:一个人拿1~m个,那谁面对m+1的局势的的时候则必败,很明显,先拿的就是要造这个局势,如果n是(m+1)*r+s(k为任意,s<m+1),那么很明显先拿的拿掉s后,然后无论下一个拿多少你都可以保证你拿完后都是拿了m+1个,这样后拿的必定面对必败局势,比如23 2,23=(3×7)+2;那我第一次拿掉2,然后无论每次第二个拿几我都可以使得这轮总共拿3,然后他必定会面对3这个局势,然后我就必胜,那什么时候必败呢,很明显如果我面对的是(m+1)的倍数的局势就必败。
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 using namespace std; 5 int main() 6 { 7 int t,n,m; 8 scanf("%d",&t); 9 while(t--) 10 { 11 scanf("%d%d",&n,&m); 12 if(n%(m+1)==0) 13 printf("second "); 14 else 15 printf("first "); 16 } 17 return 0; 18 }
这个就根本做不出来的!!!!(因为他用了黄金分割)
这思路不用掌握,因为太难了。记住就算了吧。。。
1 #include<iostream> 2 #include<cmath> 3 using namespace std; 4 int main () 5 { 6 int a,b,dif; 7 double p=(sqrt((double)5)+1)/double(2);//黄金分割 8 while(cin>>a>>b) 9 { 10 dif=abs(a-b);//取差值 11 a=a<b?a:b;//取较小的值 12 if(a==(int)(p*dif))//判断是不是奇异局势 13 printf("0 "); 14 else printf("1 "); 15 } 16 return 0; 17 }
数学题,画几个数据就明白了。题意重点:1,2,3......i,数字之间+,-都可
先发现给出n(1,2,3...),前n的和的值奇偶性由前n的和决定!
如:n=5,s=15,那么有题意,他取的值为:15,13,11,9...(为奇数)那么就清楚了。
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 using namespace std; 5 int main() 6 { 7 int s,i,d; 8 while(scanf("%d",&s)!=EOF) 9 { 10 for(i=1;i<=1000;i++) 11 { 12 d=i*(i+1)/2; 13 if(d>=s&&(d%2)==(s%2)) 14 break; 15 } 16 printf("%d ",i); 17 } 18 }
A Walk Through the Forest HDU 1142
这里考的重点还是记忆化搜索!
主要是一开始题目都没看懂,就不知道怎么进行Dfs()
如原题中:He considers taking a path from A to B to be progress if there exists a route from B to his home that is shorter than any possible route from A. (意思是:如果A到B有路,且B到家的距离要小于A到家的距离)(在已经知道最短路的情况下)
其实没看懂多少。。。不过代码讲得清楚,
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 #include<string.h> 5 using namespace std; 6 int a[1005][1005],c[1005],d[1005],dp[1005],n; 7 int max1=20000005; 8 int dfs(int k) 9 { 10 int i; 11 if(k==2) 12 return 1; 13 if(dp[k]) 14 return dp[k]; 15 for(i=1;i<=n;i++) 16 if(a[k][i]!=max1&&d[k]>d[i])//题意在这个地方 17 { 18 dp[k]+=dfs(i); 19 } 20 return dp[k]; 21 } 22 int main() 23 { 24 int m,i,j,a1,a2,a3,min1,p; 25 while(scanf("%d",&n)!=EOF) 26 { 27 if(n==0) 28 break; 29 scanf("%d",&m); 30 for(i=1;i<=n;i++) 31 for(j=1;j<=n;j++) 32 a[i][j]=max1; 33 for(i=1;i<=n;i++) 34 a[i][i]=0; 35 while(m--) 36 { 37 scanf("%d%d%d",&a1,&a2,&a3); 38 if(a[a1][a2]>a3) 39 { 40 a[a1][a2]=a3; 41 a[a2][a1]=a3; 42 } 43 } 44 memset(c,0,sizeof(c)); 45 for(i=1;i<=n;i++) 46 d[i]=a[2][i];//先从终点找最短路 47 for(i=1;i<=n;i++) 48 { 49 min1=max1; 50 for(j=1;j<=n;j++) 51 if(d[j]<min1&&!c[j]) 52 { 53 min1=d[j]; 54 p=j; 55 } 56 if(min1==max1) 57 break; 58 c[p]=1; 59 for(j=1;j<=n;j++) 60 if(d[j]>d[p]+a[p][j]&&!c[j]) 61 d[j]=d[p]+a[p][j]; 62 } 63 memset(dp,0,sizeof(dp)); 64 printf("%d ",dfs(1));//再从起点找路径数 65 } 66 }