1004 Discount
被题意给坑了,总往打折那联想。后来发现前面的和题意无关。
给出n个数, 问从1开始不存在一个在这个n个数中取某几个数的和的最小值是多少。
可以先在n个数前补一个0,排序,然后求其前缀和sum,判断sum[i-1]+1是否小于a[i],若小于则ans就是sum[i-1]+1.
简单归纳证明:
当i等于1时,显然成立,即sum[0]=0,a[1]!=1时,必然不出现1的情况。
当i>=2时,假设i-1对于上面的判断成立,即1到sum[i-1]都能由前i-1个数表示,则当sum[i-1]+1>=a[i]时,所有1到sum[i-1]+a[i](即sum[i])都是可以求和得到的(只需验证sum[i-1]到sum[i]之间是由a[i]加上之前出现的数就可以了)
#include <cstdio> #include <cstring> #include <algorithm> #define min(a,b) a>b?b:a; using namespace std; const int maxn=1005; int sum[maxn]; int a[maxn]; int main () { int n; while (~scanf("%d",&n)) { a[0]=sum[0]=0; for (int i=1 ; i<=n ; ++i) { scanf("%d",a+i); sum[i]=sum[i-1]+a[i]; } sort(a,a+n+1); int ans=sum[n]+1; for (int i=0 ; i<n ; ++i) { if(sum[i]+1<a[i+1]) ans=min(sum[i]+1,ans); } printf("%d\n",ans); } return 0; }
1005
简单DP,状态很好想到DP[i][j][1,0]表示当前处理的以i为起点j为终点,状态是1--峰 0 --谷的最多的空格数,
边界条件是dp[0][i][0]=0;即以0为起点的所有状态都是峰谷的空格数
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=105; int num[maxn][maxn];//以i为起点,j为终点的数 int dp[maxn][maxn][2];//以i为起,j为终点,1--峰,0--谷; int n; char str[maxn]; void DP() { memset (dp, -1, sizeof(dp)); for (int i=0 ; i<n ; ++i) { for (int j=i ; j<n ; ++j) { if(i==0) dp[i][j][0]=0; //1 for (int k=0 ; k<i ; ++k) { if(num[i][j]>num[k][i-1]) { dp[i][j][1]=max(dp[i][j][1], dp[k][i-1][0]+1); } //0 if(num[i][j]<num[k][i-1]) { dp[i][j][0]=max(dp[i][j][0], dp[k][i-1][1]+1); } } } } int ans=0; for (int i=0 ; i<n ; ++i) { ans=max(ans, dp[i][n-1][1]); ans=max(ans, dp[i][n-1][0]); } printf("%d\n",ans); } int main () { while (~scanf("%d%s",&n,str)) { for (int i=0 ; i<n ; ++i) { num[i][i]=str[i]-'0'; for (int j=i+1 ; j<n ; ++j) { num[i][j]=num[i][j-1]*10+str[j]-'0'; } } DP(); } return 0; }
1009 Instrction Arrangement
记忆化搜索或最长路
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; struct Edge { int v,next,w; }edge[100000+123]; int head[1005],cnt; int dis[1005]; int deg[1005]; void addedge(int u, int v, int w) { edge[cnt].v=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt; cnt++; } void init () { cnt=0; memset (head, -1 , sizeof(head)); memset (dis, -1, sizeof(dis)); memset (deg, 0, sizeof(deg)); } void dfs (int f) { int p=head[f]; if(~dis[f])return; int ans=0; for ( ; ~p ; p=edge[p].next) { dfs(edge[p].v); ans=max(dis[edge[p].v]+edge[p].w, ans); } dis[f]=ans; } int main () { int n,m; int a,b,c; while (~scanf("%d%d", &n, &m)) { init(); for (int i=0 ; i<m ; ++i) { scanf("%d%d%d", &a, &b, &c); ++deg[b]; addedge(a,b,c); } /* for (int i=0 ; i<n ; ++i) { for (int j=head[i]; ~j ; j=edge[j].next) { printf("%d %d \n", i, edge[j].v); } }*/ for (int i=0 ; i<n ; ++i) { //printf("deg==%d\n", deg[i]); if(!deg[i])addedge(n, i, 0); } dfs(n); int ans=0; for (int i=0 ; i<n ; ++i) { //printf("dis==%d\n", dis[i]); ans=max(ans, dis[i]); } printf("%d\n",ans+1); } return 0; }