2016 China Collegiate Programming Contest Final
2016 China Collegiate Programming Contest Final
Table of Contents 2016 China Collegiate Programming Contest FinalProblem A:Problem J:Problem H:
Problem A:
題意:喝咖啡,每三杯就又可以有免費一杯,求最少花費;
分析:貪心;
#include <bits/stdc++.h>using namespace std;const int inf = 0x3f3f3f3f; const int maxn = 100000+5; int a[maxn];int main() {int t;scanf("%d",&t);int kase = 0;while(t--) {int n;scanf("%d",&n);int sum = 0;for(int i=0;i<n;i++) {scanf("%d",&a[i]);sum +=a[i];}sort(a,a+n);for(int i=n-3;i>=0;i-=3)sum-=a[i];printf("Case #%d: %d\n",++kase,sum);}return 0; }Problem J:
題意:題意很長,CCPC比賽規則,給出一個隊伍,看他是否能進WF,CCPC分兩個部分,X 是從五大賽區中選X個,Y是在EC比賽中選Y個,X+Y = G,G是確定的,然后調整X,Y使得給出的這個隊伍恰好不能進WF時的最小Y,要是無論怎么調整XY,都能進WF,輸出ADVANCED!
分析:g<=20 記錄兩種規則中的這個隊伍的排名k,kk,枚舉x,y即可;
#include <bits/stdc++.h>using namespace std;string a1[25],a2[25],a3[25],a4[25],a5[25]; string ec[25];int main() {//freopen("in.txt","r",stdin);int kase = 1;int t;scanf("%d",&t);while(t--){int g;scanf("%d",&g);string ans;cin>>ans;for(int i=0; i<20; i++)cin>>a1[i];for(int i=0; i<20; i++)cin>>a2[i];for(int i=0; i<20; i++)cin>>a3[i];for(int i=0; i<20; i++)cin>>a4[i];for(int i=0;i<20;i++)cin>>a5[i];for(int i=0; i<20; i++)cin>>ec[i];int k = 1;set<string> s;bool flag = false;for(int i=0; i<20; i++){for(int j=0; j<5; j++){if(j==0){if(ans==a1[i]){flag = true;break;}else if(!s.count(a1[i])){s.insert(a1[i]);k++;continue;}}if(j==1){if(ans==a2[i]){flag = true;break;}else if(!s.count(a2[i])){s.insert(a2[i]);k++;continue;}}if(j==2){if(ans==a3[i]){flag = true;break;}else if(!s.count(a3[i])){s.insert(a3[i]);k++;continue;}}if(j==3){if(ans==a4[i]){flag = true;break;}else if(!s.count(a4[i])){s.insert(a4[i]);k++;continue;}}if(j==4){if(ans==a5[i]){flag = true;break;}else if(!s.count(a5[i])){s.insert(a5[i]);k++;continue;}}}if(flag)break;}int kk = 1;for(int i=0;i<20;i++) {if(ans==ec[i])break;else if(!s.count(ec[i])) {kk++;s.insert(ec[i]);}}int yy = -1;for(int i=0;i<=g;i++) {int x = g-i;int y = i;if(x<k&&y<kk){yy = y;break;}}if(yy==-1)printf("Case #%d: ADVANCED!\n",kase++);else printf("Case #%d: %d\n",kase++,yy);}return 0; }Problem H:
題意:n個工程項目,m 個工程師,工程師會一些項目,每一個工程項目需要一些工程項目,每個工程師只能去一個工程,求最多能完成多少個工程項目;
分析:n,m<=10 可以考慮集合上DP,考慮每一個工程師選或不選,但是不能直接用人數狀態去循環遍歷可以完成哪些項目;要優化,預處理,第i個項目,有哪些人數狀態可以完成,然后dp的時候,只要考慮這兩個集合是否有包含關系,改成了一重循環;
tip: 值得注意的是,最后的結果不是max(dp(i,(1<<m)-1)) ,而是人數的s狀態要考慮。
#include <bits/stdc++.h>using namespace std;int c[20][10],d[20][10]; int p[120];int dp[20][1<<11];int main() {int t;int n,m;scanf("%d",&t);int kase = 1;while(t--){scanf("%d%d",&n,&m);vector<int> a[20];memset(dp,0,sizeof(dp));for(int i=1; i<=n; i++){scanf("%d",&c[i][0]);for(int j=1; j<=c[i][0]; j++)scanf("%d",&c[i][j]);}for(int i=0; i<m; i++){scanf("%d",&d[i][0]);for(int j=1; j<=d[i][0]; j++)scanf("%d",&d[i][j]);}for(int i=1; i<=n; i++){for(int s=0; s<(1<<m); s++){int cnt=0;memset(p,0,sizeof(p));for(int k=0; k<m; k++){if(s&(1<<k)){cnt++;for(int j=1; j<=d[k][0]; j++)p[d[k][j]]=1;}}int flag=1;for(int j=1; j<=c[i][0]; j++)if(p[c[i][j]]==0) flag=0;if(flag) a[i].push_back(s); //第i個項目,有哪些人完成}}for(int i=1; i<=n; i++){for(int s=0; s<(1<<m); s++){for(int j=0; j<a[i].size(); j++){if((s|a[i][j])==s){dp[i][s]=max(dp[i-1][s-a[i][j]]+1,dp[i][s]);}}dp[i][s]=max(dp[i][s],dp[i-1][s]);}}printf("Case #%d: %d\n",kase++,dp[n][(1<<m)-1]);}return 0; }轉載于:https://www.cnblogs.com/TreeDream/p/7137556.html
總結
以上是生活随笔為你收集整理的2016 China Collegiate Programming Contest Final的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎样改动SharePoint管理中心的语
- 下一篇: [NOIP2005] 提高组 洛谷P10