Mixing Milk
http://www.wzoi.org/usaco/11%5C302.asp
水贪心,肯定优先选单价小的
#include <bits/stdc++.h> using namespace std; const int N = 5005; typedef long long ll; struct point{ int price, limit; void scan(){ scanf("%d%d", &price, &limit); } bool operator <(const point &I)const { return price < I.price; } }p[N]; int main() { freopen("milk.in","r",stdin); #ifndef poi freopen("milk.out","w",stdout); #endif int n, need, i, j; ll cost = 0; scanf("%d%d", &need, &n); for(i = 1; i <= n; i++) p[i].scan(); sort(p + 1, p + n + 1); for(i = 1; i <= n; i++){ int temp = min(p[i].limit, need); cost += p[i].price * temp; need -= temp; if(!need)break; } printf("%lld\n", cost); }
Barn Repair
翻译的题意非常玄妙。还是自己翻译一下吧。
牛散落在位于一维的一条直线上的牛棚上,我们可以认为他们紧挨在一起,且每个牛棚长度为1
现在最多给你M块木板,可以自由决定每一块木板的长度,使得所有的木板的长度和最小。
范围:Given M (1 <= M <= 50), the maximum number of boards that can be purchased; S (1 <= S <= 200), the total number of stalls; C (1 <= C <= S) the number of cows in the stalls, and the C occupied stall numbers (1 <= stall_number <= S), calculate the minimum number of stalls that must be blocked in order to block all the stalls that have cows in them.
分析一下,显然当用完M块模板时,自由度最大
首先可以视为一块木板,覆盖从最左边的的牛到最右边的牛。
接下来为了使长度最小,我们可以删去一块地方,最优策略就是删去最长的连续空地上的木板。这样会使木板数量+1
同理一次次做下去,直到木板数量为M
#include <bits/stdc++.h> using namespace std; const int N = 204; int len[N]; bool vis[N]; int main() { freopen("barn1.in","r",stdin); #ifndef poi freopen("barn1.out","w",stdout); #endif int n, m, s, i, j,ans, t, minpos = 202, maxpos = 0, id = 0; cin >> m >> s >> n; for(i = 1; i <= n; i++){ cin >>t; minpos = min(minpos, t); maxpos = max(maxpos, t); vis[t] = true; } ans = maxpos - minpos + 1; for(t = minpos; t <= maxpos; ){ while(vis[t] && t<= maxpos) t++; int temp = t; while(!vis[t]&&t<= maxpos)t++; len[++id] = t - temp; //printf("%d\n", len[id]); } sort(len + 1, len + id + 1); int nowused = 1; j = id; while(nowused < m && j){ ans -= len[j]; // printf("%d %d\n",nowused, ans); j--; nowused ++; } cout << ans<<endl; return 0; }
Prime Cryptarithm
http://www.wzoi.org/usaco/12%5C507.asp
暴力,最多10个数字,枚举上面的乘数的每一位是多少。最多10^5,其实更少,因为不能有前导0
坑:
前导0在枚举和检查的时候都要注意排除,所以检查要限定位数
#include <bits/stdc++.h> using namespace std; const int N = 12; int useable[N]; bool vis[N]; int n, ans = 0; int gao[10]; int upper, down; int subpro1, subpro2; bool checkdigit(int x, int len){ int i; for(i = 1; i <= len; i++){ if(!vis[x % 10])return false; x /= 10; } return true; } bool checkmidpro(){ if( max(subpro1, subpro2) >= 1000) return false;//ËÄλÊý return checkdigit(subpro1, 3) && checkdigit(subpro2, 3); } bool check(){ upper = gao[1] * 100 + gao[2] * 10 + gao[3]; down = gao[4]*10 + gao[5]; subpro1 = gao[5]*upper; subpro2 = gao[4]*upper; // cout<< subpro1 << " "<<subpro2<<endl; if(!checkmidpro()){ return false; } int fin = subpro2 * 10 + subpro1; if(fin >= 10000) return false; return checkdigit(fin, 4); } void dfs(int nowget){ if(nowget == 5){ if(check()) ans++; return; } for(int i = 1; i <= n; i++){ if(useable[i] == 0 && (nowget == 0 || nowget==3))continue; gao[nowget + 1] = useable[i]; dfs(nowget + 1); } return; } int main() { freopen("crypt1.in","r",stdin); #ifndef poi freopen("crypt1.out","w",stdout); #endif int i; cin >> n; for(i = 1; i <= n; i++){ cin >> useable[i]; vis[useable[i]] = true; } dfs(0); cout << ans<<endl; }
Combination Lock
有一把三位的锁,每位数字的范围是从1-n,转盘式,所以n后面又是1
锁有预设一个密码A,用户可以限定一个新密码B。
只要输入的密码满足:与A的每一位的距离均<=2或与B的每一位的距离均<=2,则锁可以被打开
按序输出所有可行的密码
对已有的两个密码暴力枚举每位+-2
#include <bits/stdc++.h> using namespace std; const int N = 1240000; bool vis[N]; int ok[5], get[5]; int ans= 0, n; void check(){ int has = get[1] * 50 * 50 + get[2] * 50 + get[3]; if(vis[has]) return; vis[has] = true; ans ++; // cout << get[1] <<" " << get[2] << " " << get[3] << endl;; } void dfs(int x){ int i; if(x == 3){ check(); return; } for(i = -2; i <= 2; i++){ int t = (ok[x + 1] + i + n) % n; get[x + 1] = t; dfs(x + 1); } } int main() { freopen("combo.in","r",stdin); #ifndef poi freopen("combo.out","w",stdout); #endif int i; cin >>n; for(i = 1; i <= 3; i++) { cin >> ok[i]; ok[i]--; } dfs(0); for(i = 1; i <= 3; i++) { cin >> ok[i]; ok[i] --; } dfs(0); cout << ans << endl; }
Wormholes
一个二维矩阵上面散落着一些虫洞(虫洞坐标均为整数)
人从一个方向进入虫洞后,会从虫洞对应的出口以同样的方向走
现在有个人,他沿y相同,x 增大的方向行走,问有多少种虫洞与虫洞间的对应方案能满足这个人可以在虫洞间死循环
最多12个虫洞,暴力枚举对应关系,注意不要重复计数
对于从一个洞出来后走到哪个洞,可以对坐标排序后处理出来
对于是否存在环,从一个虫洞进入后,沿对应的另一个出口,->出口通向的下一个洞搜。若无下一点则无环,否则有环
#include <bits/stdc++.h> using namespace std; const int N = 14; struct point{ int x, y; void scan(){ cin >> x >> y; } bool operator<(const point &I)const{ if(y == I.y) return x < I.x; return y < I.y; } }p[N]; int next[N], go[N]; bool vis[N]; int ans = 0; int n; bool iscircle(int x){ int now = x; while(true){ now = go[now]; now = next[now]; if(now == -1)break; if(now == x)return true; } return false; } void dfs(int num){ int i, j; if(num == n){ for(i = 1; i <= n; i++){ if(iscircle(i)) { ans ++; break; } } return ; } for(i = 1; i <= n; i++){ if(vis[i])continue; vis[i] = true; for(j = 1; j <= n; j++){ if(vis[j]) continue; vis[j] = true; go[i] = j; go[j] = i; dfs(num + 2); vis[j] = false; } vis[i] = false; break; } } int main() { freopen("wormhole.in","r",stdin); #ifndef poi freopen("wormhole.out","w",stdout); #endif memset(next, -1, sizeof(next)); cin >> n; for(int i = 1; i <= n; i++) p[i].scan(); sort(p + 1, p +n + 1); for(int i = 2; i <= n; i++) { // cout << p[i].x << " " << p[i].y<< " "<<p[i-1].y<<endl; if(p[i].y == p[i-1].y) { // cout <<"!!!!!!!!"<<endl; next[i-1] = i; } } //for(int i = 1; i <= n; i++) cout << next[i]<<endl; dfs(0); cout << ans<<endl; }
Ski Course Design
有滑雪场或者什么的东西,原有 N座山(1 <= N <= 1,000),高度非负且不超过100的整数,可修改山峰高度,每座山代价为修改的差值的平方
问最小的修改代价为多少可以使得满足最高山峰与最低之间的差值不大于17
暴力枚举最高高度,调整山峰高度后求代价
#include <bits/stdc++.h> using namespace std; const int N = 1004; const int INF = 0x3f3f3f3f; int n; int a[N]; int main() { freopen("skidesign.in","r",stdin); #ifndef poi freopen("skidesign.out","w",stdout); #endif int i, j, ans = INF, temp; cin >>n; for(i = 1; i <= n; i++){ cin >> a[i]; } sort(a + 1, a + n + 1); for(i = 100; i >= 0; i--){ temp = 0; for(j = 1; j <= n; j++){ if(a[j] < i - 17) temp += (i - 17 - a[j]) * (i - 17 - a[j]); else if(a[j]>i ) temp += (a[j]-i)*(a[j]-i); // cout << a[j] << "!!!!!" << temp<<endl; } // cout << i << " "<<temp << endl; ans = min(temp, ans); } cout <<ans<<endl; return 0; }