5 1 6 1 4 3 3 0 3 2 2 3 3 3 3 2 1 0 2 4 2 5 0 0 1 0 4 4 1 3 3 4 3 4 4
12 4
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; struct GOODS {int a, b, val;} g[110]; int n, v1, v2, m; int dp[102][102][102][6]; int main() { while(scanf("%d%d%d%d",&n,&v1,&v2,&m) != EOF) { for(int i = 1; i <= n; i++) scanf("%d%d%d",&g[i].a, &g[i].b, &g[i].val); memset(dp, 0, sizeof(dp)); for(int i = 1; i <= n; i++) for(int j = 0; j <= v1; j++) for(int k = 0; k <= v2; k++) for(int s = 0; s <= m; s++) { dp[i][j][k][s] = max(dp[i-1][j][k][s], dp[i][j][k][s]); if(j >= g[i].a) dp[i][j][k][s] = max(dp[i-1][j-g[i].a][k][s] + g[i].val, dp[i][j][k][s]); if(k >= g[i].b) dp[i][j][k][s] = max(dp[i-1][j][k-g[i].b][s] + g[i].val, dp[i][j][k][s]); if(s >= 1) dp[i][j][k][s] = max(dp[i-1][j][k][s-1] + g[i].val, dp[i][j][k][s]); } printf("%d\n", dp[n][v1][v2][m]); } return 0; }
1 10 5 1 5 100 3 10 10 5 10 100 1 4 2 6 12 266
102
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; #define MAXN 1010 int T, m, n; struct JOB {int s, t, e;} job[MAXN]; int dp[MAXN]; int cmp(const void* a, const void* b) { return ((JOB*)a)->t - ((JOB*)b)->t; } int main() { scanf("%d",&T); while(T--) { scanf("%d%d",&m,&n); for(int i = 1; i <= n; i++) scanf("%d%d%d",&job[i].s,&job[i].t,&job[i].e); qsort(job+1, n, sizeof(job[0]), cmp); memset(dp, 0, sizeof(dp)); for(int i = 1; i <= m; i++) { for(int j = 1; j <= n; j++) { if(job[j].t > i) break; dp[i] = max(dp[i], job[j].e + dp[job[j].s-1]); } } printf("%d\n", dp[m]); } return 0; }
1 5 3 3 3 3 4
0.400
分析:关系相同就是指要么3个人互相是好朋友,要么3个人互相都不是好朋友,亦即:三个点要么两两之间有一条边,要么三个点之间全都没有边。
正面考虑太困难了。所以从反面考虑:三个点之间有一条边或者两条边。
当任意选取一个点i的时候,剩下的n-1个点可以分为两个集合:{与i相连的} = b[i], {与i不相连的} = n - 1 - b[i]
所以,从两个集合中各选取一个点,再加上i点,这三个点之间要么有一条边要么有两条边,即b[i] * (n-1-b[i])种
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int C(int n, int m) { if(n <= m || m == 0) return 0; m = min(n - m, m); int ret = 1; for(int i = 1; i <= m; i++) ret = ret * (n - i + 1) / i; return ret; } int main() { int T, n; int b[1010]; scanf("%d",&T); while(T--) { scanf("%d", &n); for(int i = 0; i < n; i++) scanf("%d", &b[i]); int cnt = 0; for(int i = 0; i < n; i++) cnt += b[i] * (n - b[i] - 1); cnt /= 2; double total = (double)C(n, 3); printf("%.3lf\n", (total - cnt) / total); } return 0; }
88 90 50
6Hint样例解析: 当前比分是88:90,还剩50秒则对方还最多有一次进攻机会(最后5秒进攻不成功),我方有两次,对方的最终得分将是91, 我方至少在两回合中拿到4分才能胜利,所以所有方案数是6种,即: 第一球 第二球 1 3 2 2 2 3 3 1 3 2 3 3
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; long long dp[22][66]; void cal() { memset(dp, 0, sizeof(dp)); dp[1][1] = dp[1][2] = dp[1][3] = 1; for(int i = 2; i < 22; i++) { for(int j = 1; j < 66; j++) { if(j - 1 >= 1) dp[i][j] += dp[i-1][j-1]; if(j - 2 >= 1) dp[i][j] += dp[i-1][j-2]; if(j - 3 >= 1) dp[i][j] += dp[i-1][j-3]; } } } int main() { cal(); int a, b, t; while(scanf("%d%d%d",&a,&b,&t) != EOF) { int c = t / 15; int ca = (c + 1) / 2; int cb = c / 2; if(ca == 0) { if(a <= b) printf("0\n"); else printf("1\n"); } else { int mn = b + cb + 1 - a ; //最少得分 if(mn < 0) mn = 0; int mx = ca * 3; //最多得分 long long res = 0; for(int i = mn; i <= mx; i++) res += dp[ca][i]; printf("%I64d\n",res); //printf("%lld\n",res);错了一晚上!!坑呀! } } return 0; }